//
// 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.
//

// Note: During transition to IR, ParseContext.cpp builds the AST and IR at the same time, which is
// not efficient.  The AST is used for validation purposes, but a stack that only contains the
// necessary information needed for validation is sufficient, so for example operations such as
// constant folding etc don't need to be performed.  Such a stack could be very light, including IR
// ids that could then be used to query information out of the ir itself.
//
// This is best done when an AST-only build is no longer possible so that there wouldn't need to be
// a fallback to AST maintained at the same time.

#include "compiler/translator/ParseContext.h"
#include "common/unsafe_buffers.h"
#include "compiler/translator/Compiler.h"

#include <stdarg.h>
#include <stdio.h>

#include "common/mathutil.h"
#include "common/utilities.h"
#include "compiler/preprocessor/SourceLocation.h"
#include "compiler/translator/Declarator.h"
#include "compiler/translator/ImmutableStringBuilder.h"
#include "compiler/translator/ValidateGlobalInitializer.h"
#include "compiler/translator/glslang.h"
#include "compiler/translator/tree_util/BuiltIn.h"
#include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/util.h"

namespace sh
{

///////////////////////////////////////////////////////////////////////
//
// Sub- vector and matrix fields
//
////////////////////////////////////////////////////////////////////////

namespace
{
const int kWebGLMaxStructNesting = 4;

// Arbitrarily enforce that all types declared with a size in bytes of over 2 GB will cause
// compilation failure.
//
// For local and global variables, the limit is much lower (64KB) as that much memory won't fit in
// the GPU registers anyway.
constexpr size_t kWebGLMaxVariableSizeInBytes        = static_cast<size_t>(2) * 1024 * 1024 * 1024;
constexpr size_t kWebGLMaxPrivateVariableSizeInBytes = static_cast<size_t>(64) * 1024;
constexpr size_t kWebGLMaxTotalPrivateVariableSizeInBytes = static_cast<size_t>(16) * 1024 * 1024;

// The 1024 character identifier limit, `-2` for the `_u`
constexpr size_t kMaxAvailableIdentifierLength = 1022;

bool ShouldEnforceESSL100LoopAndIndexingLimitations(ShShaderSpec spec, int shaderVersion)
{
    // If compiling an ESSL 1.00 shader for WebGL, validate loop and indexing as well (to verify
    // that the shader only uses minimal functionality of ESSL 1.00 as in Appendix A of the spec).
    return IsWebGLBasedSpec(spec) && shaderVersion == 100;
}

struct IsSamplerFunc
{
    bool operator()(TBasicType type) { return IsSampler(type); }
};
struct IsOpaqueFunc
{
    bool operator()(TBasicType type) { return IsOpaqueType(type); }
};

template <typename OpaqueFunc>
bool ContainsOpaque(const TStructure *structType);

template <typename OpaqueFunc>
bool ContainsOpaque(const TType &type)
{
    if (OpaqueFunc{}(type.getBasicType()))
    {
        return true;
    }
    if (type.getBasicType() == EbtStruct)
    {
        return ContainsOpaque<OpaqueFunc>(type.getStruct());
    }

    return false;
}

template <typename OpaqueFunc>
bool ContainsOpaque(const TStructure *structType)
{
    for (const auto &field : structType->fields())
    {
        if (ContainsOpaque<OpaqueFunc>(*field->type()))
        {
            return true;
        }
    }
    return false;
}

// Get a token from an image argument to use as an error message token.
const char *GetImageArgumentToken(TIntermTyped *imageNode)
{
    ASSERT(IsImage(imageNode->getBasicType()));
    while (imageNode->getAsBinaryNode() &&
           (imageNode->getAsBinaryNode()->getOp() == EOpIndexIndirect ||
            imageNode->getAsBinaryNode()->getOp() == EOpIndexDirect))
    {
        imageNode = imageNode->getAsBinaryNode()->getLeft();
    }
    TIntermSymbol *imageSymbol = imageNode->getAsSymbolNode();
    if (imageSymbol)
    {
        return imageSymbol->getName().data();
    }
    return "image";
}

bool CanSetDefaultPrecisionOnType(const TPublicType &type)
{
    if (!SupportsPrecision(type.getBasicType()))
    {
        return false;
    }
    if (type.getBasicType() == EbtUInt)
    {
        // ESSL 3.00.4 section 4.5.4
        return false;
    }
    if (type.isAggregate())
    {
        // Not allowed to set for aggregate types
        return false;
    }
    return true;
}

// Map input primitive types to input array sizes in a geometry shader.
GLuint GetGeometryShaderInputArraySize(TLayoutPrimitiveType primitiveType)
{
    switch (primitiveType)
    {
        case EptPoints:
            return 1u;
        case EptLines:
            return 2u;
        case EptTriangles:
            return 3u;
        case EptLinesAdjacency:
            return 4u;
        case EptTrianglesAdjacency:
            return 6u;
        default:
            UNREACHABLE();
            return 0u;
    }
}

bool IsBufferOrSharedVariable(TIntermTyped *var)
{
    if (var->isInterfaceBlock() || var->getQualifier() == EvqBuffer ||
        var->getQualifier() == EvqShared)
    {
        return true;
    }
    return false;
}

TIntermTyped *FindLValueBase(TIntermTyped *node)
{
    do
    {
        const TIntermBinary *binary = node->getAsBinaryNode();
        if (binary == nullptr)
        {
            return node;
        }

        TOperator op = binary->getOp();
        if (op != EOpIndexDirect && op != EOpIndexIndirect)
        {
            return static_cast<TIntermTyped *>(nullptr);
        }

        node = binary->getLeft();
    } while (true);
}

void AddAdvancedBlendEquation(gl::BlendEquationType eq, TLayoutQualifier *qualifier)
{
    qualifier->advancedBlendEquations.set(static_cast<uint32_t>(eq));
}

constexpr bool IsValidWithPixelLocalStorage(TLayoutImageInternalFormat internalFormat)
{
    switch (internalFormat)
    {
        case EiifRGBA8:
        case EiifRGBA8I:
        case EiifRGBA8UI:
        case EiifR32F:
        case EiifR32I:
        case EiifR32UI:
            return true;
        default:
            return false;
    }
}

constexpr ShPixelLocalStorageFormat ImageFormatToPLSFormat(TLayoutImageInternalFormat format)
{
    switch (format)
    {
        default:
            return ShPixelLocalStorageFormat::NotPLS;
        case EiifRGBA8:
            return ShPixelLocalStorageFormat::RGBA8;
        case EiifRGBA8I:
            return ShPixelLocalStorageFormat::RGBA8I;
        case EiifRGBA8UI:
            return ShPixelLocalStorageFormat::RGBA8UI;
        case EiifR32F:
            return ShPixelLocalStorageFormat::R32F;
        case EiifR32I:
            return ShPixelLocalStorageFormat::R32I;
        case EiifR32UI:
            return ShPixelLocalStorageFormat::R32UI;
    }
}

bool UsesDerivatives(TIntermAggregate *functionCall)
{
    const TOperator op = functionCall->getOp();
    if (BuiltInGroup::IsDerivativesFS(op))
    {
        return true;
    }
    switch (op)
    {
        // TextureFirstVersions with implicit LOD
        case EOpTexture2D:
        case EOpTexture2DProj:
        case EOpTextureCube:
        case EOpTexture3D:
        case EOpTexture3DProj:
        case EOpShadow2DEXT:
        case EOpShadow2DProjEXT:
        // TextureFirstVersionsBias
        case EOpTexture2DBias:
        case EOpTexture2DProjBias:
        case EOpTextureCubeBias:
        case EOpTexture3DBias:
        case EOpTexture3DProjBias:
        // TextureNoBias
        case EOpTexture:
        case EOpTextureProj:
        // TextureBias
        case EOpTextureBias:
        case EOpTextureProjBias:
        // TextureOffsetNoBias
        case EOpTextureOffset:
        case EOpTextureProjOffset:
        // TextureOffsetBias
        case EOpTextureOffsetBias:
        case EOpTextureProjOffsetBias:
        // TextureQueryLod
        case EOpTextureQueryLOD:
            return true;
        default:
            return false;
    }
}

bool IsSamplerOrStructWithOnlySamplers(const TType *type)
{
    return IsSampler(type->getBasicType()) || type->isStructureContainingOnlySamplers();
}

void MarkClipCullFirstEncounter(const TSourceLoc &line, ClipCullDistanceInfo *info)
{
    if (info->firstEncounter.first_line < 0)
    {
        info->firstEncounter = line;
    }
}

void MarkClipCullRedeclaredSize(const TSourceLoc &line,
                                uint32_t arraySize,
                                ClipCullDistanceInfo *info)
{
    MarkClipCullFirstEncounter(line, info);
    info->size = arraySize;
}

void MarkClipCullArrayLengthMethodCall(const TSourceLoc &line, ClipCullDistanceInfo *info)
{
    MarkClipCullFirstEncounter(line, info);
    info->hasArrayLengthMethodCall = true;
}

void MarkClipCullIndex(const TSourceLoc &line, TIntermTyped *indexExpr, ClipCullDistanceInfo *info)
{
    MarkClipCullFirstEncounter(line, info);
    const TConstantUnion *constIdx = indexExpr->getConstantValue();
    if (constIdx)
    {
        int idx = 0;
        switch (constIdx->getType())
        {
            case EbtInt:
                idx = constIdx->getIConst();
                break;
            case EbtUInt:
                idx = constIdx->getUConst();
                break;
            default:
                // This can happen due to a compile error that is generated elsewhere.
                break;
        }

        info->maxIndex = std::max(info->maxIndex, idx);
    }
    else
    {
        info->hasNonConstIndex = true;
    }
}

void ValidateFragColorAndFragData(GLenum shaderType,
                                  int shaderVersion,
                                  const TSymbolTable &symbolTable,
                                  TDiagnostics *diagnostics)
{
    if (shaderVersion > 100 || shaderType != GL_FRAGMENT_SHADER)
    {
        return;
    }

    bool usesFragColor = false;
    bool usesFragData  = false;
    // This validation is a bit stricter than the spec - it's only an error to write to
    // both FragData and FragColor. But because it's better not to have reads from undefined
    // variables, we always return an error if they are both referenced, rather than only if they
    // are written.
    if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_FragColor()) ||
        symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT()))
    {
        usesFragColor = true;
    }
    const bool secondaryFragDataUsed = symbolTable.isSecondaryFragDataUsed();
    if (symbolTable.isStaticallyUsed(*symbolTable.gl_FragData()) || secondaryFragDataUsed)
    {
        usesFragData = true;
    }
    if (usesFragColor && usesFragData)
    {
        const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
        if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT()) ||
            secondaryFragDataUsed)
        {
            errorMessage =
                "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
                " and (gl_FragColor, gl_SecondaryFragColorEXT)";
        }
        diagnostics->globalError(errorMessage);
    }
}

bool IsESSL100ConstantExpression(TIntermNode *node)
{
    return node->getAsConstantUnion() != nullptr && node->getAsTyped()->getQualifier() == EvqConst;
}

// Calculate the size of a variable for validation purposes.  If the variable is a UBO, add padding
// that makes the calculated size _at least_ as large as std140 requires.  Given the limits are
// arbitrary and overly large, there is no need to be precise about this calculation as long as the
// calculated size is an overestimation of the real size (which could be, by a small amount).
angle::base::CheckedNumeric<size_t> CalculateVariableSize(const TType *type, bool isStd140)
{
    constexpr size_t kVec4Size = sizeof(float) * 4;

    if (type->isArray())
    {
        TType elementType = *type;
        elementType.toArrayElementType();
        angle::base::CheckedNumeric<size_t> elementSize =
            CalculateVariableSize(&elementType, isStd140);

        return elementSize * type->getArraySizeProduct();
    }

    if (type->getBasicType() == EbtStruct || type->getBasicType() == EbtInterfaceBlock)
    {
        const TFieldList &fields                      = type->getBasicType() == EbtStruct
                                                            ? type->getStruct()->fields()
                                                            : type->getInterfaceBlock()->fields();
        angle::base::CheckedNumeric<size_t> totalSize = 0;
        for (const TField *field : fields)
        {
            const TType *fieldType = field->type();
            totalSize += CalculateVariableSize(fieldType, isStd140);
        }
        return totalSize;
    }

    if (type->isMatrix())
    {
        if (isStd140)
        {
            // Ignore row vs column major, and get the biggest size of the two possibilities as a
            // possibly slight overestimation.  Note that the size according to std140 is either
            // rows times vec4 or cols times vec4 based on how the matrix is laid out.
            return std::max(type->getRows(), type->getCols()) * kVec4Size;
        }
        else
        {
            return type->getRows() * type->getCols() * sizeof(float);
        }
    }

    // For vectors and scalars, return the size of a vec4 for std140.  This is a slight
    // overestimation.  If this is the element of an array though, it's accurate (which is why it's
    // a slight overestimation, e.g. the size of a large array of a scalar type is not
    // overestimated).
    return isStd140 ? kVec4Size : type->getNominalSize() * sizeof(float);
}

unsigned int GetMaxUniformBlocksForShaderType(sh::GLenum shaderType,
                                              const ShCompileOptions &options,
                                              const ShBuiltInResources &resources)
{
    // If the validatePerStageMaxUniformBlocks workaround is disabled. Set a limit that will not be
    // hit.
    if (!options.validatePerStageMaxUniformBlocks)
    {
        return std::numeric_limits<unsigned int>::max();
    }

    switch (shaderType)
    {
        case GL_FRAGMENT_SHADER:
            return resources.MaxFragmentUniformBlocks;
        case GL_VERTEX_SHADER:
            return resources.MaxVertexUniformBlocks;
        case GL_COMPUTE_SHADER:
            return resources.MaxComputeUniformBlocks;
        case GL_GEOMETRY_SHADER:
            return resources.MaxGeometryUniformBlocks;
        case GL_TESS_CONTROL_SHADER:
            return resources.MaxTessControlUniformBlocks;
        case GL_TESS_EVALUATION_SHADER:
            return resources.MaxTessEvaluationUniformBlocks;
        default:
            UNREACHABLE();
            return 0;
    }
}

enum class StructureOriginalScope
{
    Global,
    FunctionLocal,
};

TIntermDeclaration *RenameAndDeclareStruct(TSymbolTable *symbolTable,
                                           TStructure *structure,
                                           StructureOriginalScope scope)
{
    ASSERT(!structure->name().empty());

    // We need +2 space for _0 if global, or +11 for "_uniqueId" if function-local.  Using +11
    // always for simplicity.  +1 for the NUL terminator.
    //
    // If appending ID and the name is too long, cut off the end of the name.  The ID makes it
    // unique.
    constexpr uint32_t kAppendExtraChars = 1 + 11;  // underscore + 32-bit number
    const ImmutableString name(
        structure->name().data(),
        std::min<size_t>(structure->name().length(), kESSLMaxIdentifierLength - kAppendExtraChars));

    ImmutableStringBuilder builder(structure->name().length() + kAppendExtraChars);
    builder << name << "_"
            << (scope == StructureOriginalScope::Global ? 0 : structure->uniqueId().get());
    structure->setName(builder);

    TType *namedType = new TType(structure, true);
    namedType->setQualifier(EvqGlobal);

    TVariable *structVariable =
        new TVariable(symbolTable, kEmptyImmutableString, namedType, SymbolType::Empty);
    TIntermSymbol *structDeclarator       = new TIntermSymbol(structVariable);
    TIntermDeclaration *structDeclaration = new TIntermDeclaration;
    structDeclaration->appendDeclarator(structDeclarator);
    return structDeclaration;
}
}  // namespace

// This tracks each binding point's current default offset for inheritance of subsequent
// variables using the same binding, and keeps offsets unique and non overlapping.
// See GLSL ES 3.1, section 4.4.6.
class TParseContext::AtomicCounterBindingState
{
  public:
    AtomicCounterBindingState() : mDefaultOffset(0) {}
    // Inserts a new span and returns -1 if overlapping, else returns the starting offset of
    // newly inserted span.
    int insertSpan(int start, size_t length)
    {
        gl::RangeI newSpan(start, start + static_cast<int>(length));
        for (const auto &span : mSpans)
        {
            if (newSpan.intersects(span))
            {
                return -1;
            }
        }
        mSpans.push_back(newSpan);
        mDefaultOffset = newSpan.high();
        return start;
    }
    // Inserts a new span starting from the default offset.
    int appendSpan(size_t length) { return insertSpan(mDefaultOffset, length); }
    void setDefaultOffset(int offset) { mDefaultOffset = offset; }

  private:
    int mDefaultOffset;
    std::vector<gl::RangeI> mSpans;
};

TParseContext::TParseContext(TSymbolTable &symt,
                             TExtensionBehavior &ext,
                             sh::GLenum type,
                             ShShaderSpec spec,
                             const ShCompileOptions &options,
                             TDiagnostics *diagnostics,
                             const ShBuiltInResources &resources,
                             ShShaderOutput outputType)
    : symbolTable(symt),
      mDeferredNonEmptyDeclarationErrorCheck(false),
      mShaderType(type),
      mShaderSpec(spec),
      mCompileOptions(options),
      mResources(resources),
      mShaderVersion(100),
      mTreeRoot(nullptr),
      mStructNestingLevel(0),
      mCurrentFunction(nullptr),
      mFunctionReturnsValue(false),
      mEarlyFragmentTestsSpecified(false),
      mHasDiscard(false),
      mSampleQualifierSpecified(false),
      mPositionRedeclaredForSeparateShaderObject(false),
      mPointSizeRedeclaredForSeparateShaderObject(false),
      mPositionOrPointSizeUsedForSeparateShaderObject(false),
      mUsesDerivatives(false),
      mDefaultUniformMatrixPacking(EmpColumnMajor),
      mDefaultUniformBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared),
      mDefaultBufferMatrixPacking(EmpColumnMajor),
      mDefaultBufferBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared),
      mDiagnostics(diagnostics),
      mDirectiveHandler(ext, *mDiagnostics, *this, mShaderType),
      mPreprocessor(mDiagnostics,
                    &mDirectiveHandler,
                    angle::pp::PreprocessorSettings(
                        spec,
                        options.allowExtensionDisableAfterNonPPTokensInWebGL
                            ? angle::pp::WebGLExtensionDisableBehavior::AnywhereInShader
                            : angle::pp::WebGLExtensionDisableBehavior::Standard)),
      mScanner(nullptr),
      mComputeShaderLocalSizeDeclared(false),
      mComputeShaderLocalSize(-1),
      mNumViews(-1),
      mMaxUniformBlocks(GetMaxUniformBlocksForShaderType(mShaderType, options, resources)),
      mNumUniformBlocks(0),
      mDeclaringFunction(false),
      mDeclaringMain(false),
      mMainFunction(nullptr),
      mIsReturnVisitedInMain(false),
      mValidateESSL100Limitations(
          ShouldEnforceESSL100LoopAndIndexingLimitations(spec, mShaderVersion)),
      mFragmentOutputIndex1Used(false),
      mFragmentOutputFragDepthUsed(false),
      mMaxFragDataArrayIndexUsed(0),
      mGeometryShaderInputPrimitiveType(EptUndefined),
      mGeometryShaderOutputPrimitiveType(EptUndefined),
      mGeometryShaderInvocations(0),
      mGeometryShaderMaxVertices(-1),
      mGeometryInputArraySize(0),
      mTessControlShaderOutputVertices(0),
      mTessEvaluationShaderInputPrimitiveType(EtetUndefined),
      mTessEvaluationShaderInputVertexSpacingType(EtetUndefined),
      mTessEvaluationShaderInputOrderingType(EtetUndefined),
      mTessEvaluationShaderInputPointType(EtetUndefined),
      mHasAnyPreciseType(false),
      mAdvancedBlendEquations(0),
      mFunctionBodyNewScope(false),
      mOutputType(outputType),
      mIRBuilder(gl::FromGLenum<gl::ShaderType>(type), options)
{
    mDiagnostics->setIRBuilder(&mIRBuilder);

    // If not using the IR, don't build it by pretending there's been an error.
    if (!mCompileOptions.useIR)
    {
        mIRBuilder.onError();
    }
}

TParseContext::~TParseContext()
{
    mDiagnostics->setIRBuilder(nullptr);
}

ir::IR TParseContext::getIR()
{
    // Set advanced blend if specified.  This is not done during parse because multiple statements
    // accumulate modes.
    if (mAdvancedBlendEquations.any())
    {
        mIRBuilder.setAdvancedBlendEquations(mAdvancedBlendEquations.bits());
    }

    return ir::Builder::destroy(std::move(mIRBuilder));
}

void TParseContext::onShaderVersionDeclared(const TSourceLoc &loc, int version)
{
    mShaderVersion = version;
    checkShaderVersion(loc);
    // Update cached decisions that depend on the shader version
    mValidateESSL100Limitations =
        ShouldEnforceESSL100LoopAndIndexingLimitations(mShaderSpec, mShaderVersion);
}

void TParseContext::fatal(const TSourceLoc &loc, const char *reason)
{
    error(loc, reason, "");
    mPreprocessor.forceEOF();
}

bool TParseContext::checkShaderVersion(const TSourceLoc &loc)
{
    if (GetMaxShaderVersionForSpec(mShaderSpec) < mShaderVersion)
    {
        std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
        reasonStream << "unsupported shader version ";
        reasonStream << mShaderVersion;
        fatal(loc, reasonStream.str().c_str());
        return false;
    }

    switch (mShaderType)
    {
        case GL_COMPUTE_SHADER:
            if (mShaderVersion < 310)
            {
                fatal(loc, "Compute shader is not supported in this shader version.");
                return false;
            }
            break;

        case GL_GEOMETRY_SHADER_EXT:
            if (mShaderVersion < 310)
            {
                fatal(loc, "Geometry shader is not supported in this shader version.");
                return false;
            }
            break;

        case GL_TESS_CONTROL_SHADER_EXT:
        case GL_TESS_EVALUATION_SHADER_EXT:
            if (mShaderVersion < 310)
            {
                fatal(loc, "Tessellation shaders are not supported in this shader version.");
                return false;
            }
            break;

        default:
            break;
    }

    return true;
}

bool TParseContext::checkCanUseShaderType(const TSourceLoc &loc)
{
    switch (mShaderType)
    {
        case GL_GEOMETRY_SHADER_EXT:
            if (mShaderVersion == 310)
            {
                if (!checkCanUseOneOfExtensions(
                        loc, std::array<TExtension, 2u>{{TExtension::EXT_geometry_shader,
                                                         TExtension::OES_geometry_shader}}))
                {
                    return false;
                }
            }
            break;

        case GL_TESS_CONTROL_SHADER_EXT:
        case GL_TESS_EVALUATION_SHADER_EXT:
            if (mShaderVersion == 310)
            {
                if (!checkCanUseOneOfExtensions(
                        loc, std::array<TExtension, 2u>{{TExtension::EXT_tessellation_shader,
                                                         TExtension::OES_tessellation_shader}}))
                {
                    return false;
                }
            }
            break;

        default:
            break;
    }

    return true;
}

bool TParseContext::anyMultiviewExtensionAvailable()
{
    return isExtensionEnabled(TExtension::OVR_multiview) ||
           isExtensionEnabled(TExtension::OVR_multiview2);
}

bool TParseContext::parseVectorFields(const TSourceLoc &line,
                                      const ImmutableString &compString,
                                      uint32_t vecSize,
                                      TVector<uint32_t> *fieldOffsets)
{
    ASSERT(fieldOffsets);
    size_t fieldCount = compString.length();
    if (fieldCount > 4u)
    {
        error(line, "illegal vector field selection", compString);
        return false;
    }
    fieldOffsets->resize(fieldCount);

    enum
    {
        exyzw,
        ergba,
        estpq
    } fieldSet[4];

    for (unsigned int i = 0u; i < fieldOffsets->size(); ++i)
    {
        switch (compString[i])
        {
            case 'x':
                ANGLE_UNSAFE_TODO({
                    (*fieldOffsets)[i] = 0;
                    fieldSet[i]        = exyzw;
                })
                break;
            case 'r':
                ANGLE_UNSAFE_TODO({
                    (*fieldOffsets)[i] = 0;
                    fieldSet[i]        = ergba;
                })
                break;
            case 's':
                ANGLE_UNSAFE_TODO({
                    (*fieldOffsets)[i] = 0;
                    fieldSet[i]        = estpq;
                })
                break;
            case 'y':
                ANGLE_UNSAFE_TODO({
                    (*fieldOffsets)[i] = 1;
                    fieldSet[i]        = exyzw;
                })
                break;
            case 'g':
                ANGLE_UNSAFE_TODO({
                    (*fieldOffsets)[i] = 1;
                    fieldSet[i]        = ergba;
                })
                break;
            case 't':
                ANGLE_UNSAFE_TODO({
                    (*fieldOffsets)[i] = 1;
                    fieldSet[i]        = estpq;
                })
                break;
            case 'z':
                ANGLE_UNSAFE_TODO({
                    (*fieldOffsets)[i] = 2;
                    fieldSet[i]        = exyzw;
                })
                break;
            case 'b':
                ANGLE_UNSAFE_TODO({
                    (*fieldOffsets)[i] = 2;
                    fieldSet[i]        = ergba;
                })
                break;
            case 'p':
                ANGLE_UNSAFE_TODO({
                    (*fieldOffsets)[i] = 2;
                    fieldSet[i]        = estpq;
                })
                break;

            case 'w':
                ANGLE_UNSAFE_TODO({
                    (*fieldOffsets)[i] = 3;
                    fieldSet[i]        = exyzw;
                })
                break;
            case 'a':
                ANGLE_UNSAFE_TODO({
                    (*fieldOffsets)[i] = 3;
                    fieldSet[i]        = ergba;
                })
                break;
            case 'q':
                ANGLE_UNSAFE_TODO({
                    (*fieldOffsets)[i] = 3;
                    fieldSet[i]        = estpq;
                })
                break;
            default:
                error(line, "illegal vector field selection", compString);
                return false;
        }
    }

    for (unsigned int i = 0u; i < fieldOffsets->size(); ++i)
    {
        if ((*fieldOffsets)[i] >= vecSize)
        {
            error(line, "vector field selection out of range", compString);
            return false;
        }

        if (i > 0)
        {
            if (ANGLE_UNSAFE_TODO(fieldSet[i] != fieldSet[i - 1]))
            {
                error(line, "illegal - vector component fields not from the same set", compString);
                return false;
            }
        }
    }

    return true;
}

///////////////////////////////////////////////////////////////////////
//
// Errors
//
////////////////////////////////////////////////////////////////////////

//
// Used by flex/bison to output all syntax and parsing errors.
//
void TParseContext::error(const TSourceLoc &loc, const char *reason, const char *token)
{
    mDiagnostics->error(loc, reason, token);
}

void TParseContext::error(const TSourceLoc &loc, const char *reason, const ImmutableString &token)
{
    mDiagnostics->error(loc, reason, token.data());
}

void TParseContext::warning(const TSourceLoc &loc, const char *reason, const char *token)
{
    mDiagnostics->warning(loc, reason, token);
}

void TParseContext::errorIfPLSDeclared(const TSourceLoc &loc, PLSIllegalOperations op)
{
    if (!isExtensionEnabled(TExtension::ANGLE_shader_pixel_local_storage))
    {
        return;
    }
    if (mPLSLayouts.empty())
    {
        // No pixel local storage uniforms have been declared yet. Remember this potential error in
        // case PLS gets declared later.
        mPLSPotentialErrors.emplace_back(loc, op);
        return;
    }
    switch (op)
    {
        case PLSIllegalOperations::Discard:
            error(loc, "illegal discard when pixel local storage is declared", "discard");
            break;
        case PLSIllegalOperations::ReturnFromMain:
            error(loc, "illegal return from main when pixel local storage is declared", "return");
            break;
        case PLSIllegalOperations::AssignFragDepth:
            error(loc, "value not assignable when pixel local storage is declared", "gl_FragDepth");
            break;
        case PLSIllegalOperations::AssignSampleMask:
            error(loc, "value not assignable when pixel local storage is declared",
                  "gl_SampleMask");
            break;
        case PLSIllegalOperations::FragDataIndexNonzero:
            error(loc, "illegal nonzero index qualifier when pixel local storage is declared",
                  "layout");
            break;
        case PLSIllegalOperations::EnableAdvancedBlendEquation:
            error(loc, "illegal advanced blend equation when pixel local storage is declared",
                  "layout");
            break;
    }
}

void TParseContext::outOfRangeError(bool isError,
                                    const TSourceLoc &loc,
                                    const char *reason,
                                    const char *token)
{
    if (isError)
    {
        error(loc, reason, token);
    }
    else
    {
        warning(loc, reason, token);
    }
}

void TParseContext::setTreeRoot(TIntermBlock *treeRoot)
{
#ifdef ANGLE_IR
    // When the IR is used, make sure the temporary tree created during parse is not used by anyone.
    // With IR, eventually this tree doesn't need to be created at all, a stack of node properties
    // to verify / propagate is sufficient during parse for validation purposes.
    if (mCompileOptions.useIR)
    {
        return;
    }
#endif
    mTreeRoot = treeRoot;
    mTreeRoot->setIsTreeRoot();
}

//
// Same error message for all places assignments don't work.
//
void TParseContext::assignError(const TSourceLoc &line,
                                const char *op,
                                const TType &left,
                                const TType &right)
{
    TInfoSinkBase reasonStream;
    reasonStream << "cannot convert from '" << right << "' to '" << left << "'";
    error(line, reasonStream.c_str(), op);
}

//
// Same error message for all places unary operations don't work.
//
void TParseContext::unaryOpError(const TSourceLoc &line, const char *op, const TType &operand)
{
    TInfoSinkBase reasonStream;
    reasonStream << "wrong operand type - no operation '" << op
                 << "' exists that takes an operand of type " << operand
                 << " (or there is no acceptable conversion)";
    error(line, reasonStream.c_str(), op);
}

//
// Same error message for all binary operations don't work.
//
void TParseContext::binaryOpError(const TSourceLoc &line,
                                  const char *op,
                                  const TType &left,
                                  const TType &right)
{
    TInfoSinkBase reasonStream;
    reasonStream << "wrong operand types - no operation '" << op
                 << "' exists that takes a left-hand operand of type '" << left
                 << "' and a right operand of type '" << right
                 << "' (or there is no acceptable conversion)";
    error(line, reasonStream.c_str(), op);
}

void TParseContext::checkPrecisionSpecified(const TSourceLoc &line,
                                            TPrecision precision,
                                            TBasicType type)
{
    if (precision != EbpUndefined && !SupportsPrecision(type))
    {
        error(line, "illegal type for precision qualifier", getBasicString(type));
    }

    if (precision == EbpUndefined)
    {
        switch (type)
        {
            case EbtFloat:
                error(line, "No precision specified for (float)", "");
                return;
            case EbtInt:
            case EbtUInt:
                UNREACHABLE();  // there's always a predeclared qualifier
                error(line, "No precision specified (int)", "");
                return;
            default:
                if (IsOpaqueType(type))
                {
                    error(line, "No precision specified", getBasicString(type));
                    return;
                }
        }
    }
}

void TParseContext::markStaticUseIfSymbol(TIntermNode *node)
{
    TIntermSwizzle *swizzleNode = node->getAsSwizzleNode();
    if (swizzleNode)
    {
        markStaticUseIfSymbol(swizzleNode->getOperand());
        return;
    }
    TIntermBinary *binaryNode = node->getAsBinaryNode();
    if (binaryNode)
    {
        switch (binaryNode->getOp())
        {
            case EOpIndexDirect:
            case EOpIndexIndirect:
            case EOpIndexDirectStruct:
            case EOpIndexDirectInterfaceBlock:
                markStaticUseIfSymbol(binaryNode->getLeft());
                return;
            default:
                return;
        }
    }
    TIntermSymbol *symbolNode = node->getAsSymbolNode();
    if (symbolNode)
    {
        symbolTable.markStaticUse(symbolNode->variable());
    }
}

// Both test and if necessary, spit out an error, to see if the node is really
// an l-value that can be operated on this way.
bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node)
{
    TIntermSwizzle *swizzleNode = node->getAsSwizzleNode();
    if (swizzleNode)
    {
        bool ok = checkCanBeLValue(line, op, swizzleNode->getOperand());
        if (ok && swizzleNode->hasDuplicateOffsets())
        {
            error(line, " l-value of swizzle cannot have duplicate components", op);
            return false;
        }
        return ok;
    }

    TIntermBinary *binaryNode = node->getAsBinaryNode();
    if (binaryNode)
    {
        switch (binaryNode->getOp())
        {
            case EOpIndexDirect:
            case EOpIndexIndirect:
            case EOpIndexDirectStruct:
            case EOpIndexDirectInterfaceBlock:
                if (node->getMemoryQualifier().readonly)
                {
                    error(line, "can't modify a readonly variable", op);
                    return false;
                }
                return checkCanBeLValue(line, op, binaryNode->getLeft());
            default:
                break;
        }
        error(line, " l-value required", op);
        return false;
    }

    std::string message;
    switch (node->getQualifier())
    {
        case EvqConst:
            message = "can't modify a const";
            break;
        case EvqParamConst:
            message = "can't modify a const";
            break;
        case EvqAttribute:
            message = "can't modify an attribute";
            break;
        case EvqFragmentIn:
        case EvqVertexIn:
        case EvqGeometryIn:
        case EvqTessControlIn:
        case EvqTessEvaluationIn:
        case EvqSmoothIn:
        case EvqFlatIn:
        case EvqNoPerspectiveIn:
        case EvqCentroidIn:
        case EvqSampleIn:
        case EvqNoPerspectiveCentroidIn:
        case EvqNoPerspectiveSampleIn:
        case EvqPatchIn:
            message = "can't modify an input";
            break;
        case EvqUniform:
            message = "can't modify a uniform";
            break;
        case EvqVaryingIn:
            message = "can't modify a varying";
            break;
        case EvqInstanceID:
            message = "can't modify gl_InstanceID";
            break;
        case EvqVertexID:
            message = "can't modify gl_VertexID";
            break;
        case EvqBaseVertex:
            message = "can't modify gl_BaseVertex";
            break;
        case EvqBaseInstance:
            message = "can't modify gl_BaseInstance";
            break;
        case EvqDrawID:
            message = "can't modify gl_DrawID";
            break;
        case EvqFragCoord:
            message = "can't modify gl_FragCoord";
            break;
        case EvqFrontFacing:
            message = "can't modify gl_FrontFacing";
            break;
        case EvqHelperInvocation:
            message = "can't modify gl_HelperInvocation";
            break;
        case EvqPointCoord:
            message = "can't modify gl_PointCoord";
            break;
        case EvqNumWorkGroups:
            message = "can't modify gl_NumWorkGroups";
            break;
        case EvqWorkGroupSize:
            message = "can't modify gl_WorkGroupSize";
            break;
        case EvqWorkGroupID:
            message = "can't modify gl_WorkGroupID";
            break;
        case EvqLocalInvocationID:
            message = "can't modify gl_LocalInvocationID";
            break;
        case EvqGlobalInvocationID:
            message = "can't modify gl_GlobalInvocationID";
            break;
        case EvqLocalInvocationIndex:
            message = "can't modify gl_LocalInvocationIndex";
            break;
        case EvqViewIDOVR:
            message = "can't modify gl_ViewID_OVR";
            break;
        case EvqDepthRange:
            message = "can't modify gl_DepthRange";
            break;
        case EvqComputeIn:
            message = "can't modify work group size variable";
            break;
        case EvqPerVertexIn:
            message = "can't modify any member in gl_in";
            break;
        case EvqPrimitiveIDIn:
            message = "can't modify gl_PrimitiveIDIn";
            break;
        case EvqInvocationID:
            message = "can't modify gl_InvocationID";
            break;
        case EvqPrimitiveID:
            if (mShaderType == GL_FRAGMENT_SHADER)
            {
                message = "can't modify gl_PrimitiveID in a fragment shader";
            }
            break;
        case EvqLayerIn:
            message = "can't modify gl_Layer in a fragment shader";
            break;
        case EvqShadingRateEXT:
            message = "can't modify gl_ShadingRateEXT";
            break;
        case EvqSampleID:
            message = "can't modify gl_SampleID";
            break;
        case EvqSampleMaskIn:
            message = "can't modify gl_SampleMaskIn";
            break;
        case EvqSamplePosition:
            message = "can't modify gl_SamplePosition";
            break;
        case EvqNumSamples:
            message = "can't modify gl_NumSamples";
            break;
        case EvqPatchVerticesIn:
            message = "can't modify gl_PatchVerticesIn";
            break;
        case EvqTessCoord:
            message = "can't modify gl_TessCoord";
            break;
        case EvqClipDistance:
            if (mShaderType == GL_FRAGMENT_SHADER)
            {
                message = "can't modify gl_ClipDistance in a fragment shader";
            }
            break;
        case EvqCullDistance:
            if (mShaderType == GL_FRAGMENT_SHADER)
            {
                message = "can't modify gl_CullDistance in a fragment shader";
            }
            break;
        case EvqFragDepth:
            errorIfPLSDeclared(line, PLSIllegalOperations::AssignFragDepth);
            break;
        case EvqSampleMask:
            errorIfPLSDeclared(line, PLSIllegalOperations::AssignSampleMask);
            break;
        default:
            //
            // Type that can't be written to?
            //
            if (node->getBasicType() == EbtVoid)
            {
                message = "can't modify void";
            }
            if (IsOpaqueType(node->getBasicType()))
            {
                message = "can't modify a variable with type ";
                message += getBasicString(node->getBasicType());
            }
            else if (node->getMemoryQualifier().readonly)
            {
                message = "can't modify a readonly variable";
            }
    }

    // Disallow modification of structs that have samplers, even if the field being modified is not
    // a sampler for example in code like this:
    //
    //     void f(StructWithSampler s) {
    //         s.non_sampler = 1.0;
    //     }
    //
    // The above is valid GLSL code, but is not currently supported due to limitations of the
    // MonomorphizeUnsupportedFunctions pass.  On mesa/GL drivers, where
    // MonomorphizeUnsupportedFunctions is not used, code like the above crashes the compiler.
    if (message.empty())
    {
        TIntermTyped *lvalueBase = FindLValueBase(node);
        if (lvalueBase->getType().isStructureContainingSamplers())
        {
            message = "modifying structures containing samplers is not currently supported";
        }
    }

    ASSERT(binaryNode == nullptr && swizzleNode == nullptr);
    TIntermSymbol *symNode = node->getAsSymbolNode();
    if (message.empty() && symNode != nullptr)
    {
        if (mValidateESSL100Limitations)
        {
            checkESSL100NoLoopSymbolAssign(symNode, line);
        }
        if (mCompileOptions.rejectWebglShadersWithUndefinedBehavior)
        {
            // For simplicity, if a variable is written to, assume it's no longer always true.
            mConstantTrueVariables.erase(symNode->variable().uniqueId());
        }

        symbolTable.markStaticUse(symNode->variable());
        return true;
    }

    std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
    reasonStream << "l-value required";
    if (!message.empty())
    {
        if (symNode)
        {
            // Symbol inside an expression can't be nameless.
            ASSERT(symNode->variable().symbolType() != SymbolType::Empty);
            const ImmutableString &symbol = symNode->getName();
            reasonStream << " (" << message << " \"" << symbol << "\")";
        }
        else
        {
            reasonStream << " (" << message << ")";
        }
    }
    std::string reason = reasonStream.str();
    error(line, reason.c_str(), op);

    return false;
}

// Both test, and if necessary spit out an error, to see if the node is really
// a constant.
void TParseContext::checkIsConst(TIntermTyped *node)
{
    if (node->getQualifier() != EvqConst)
    {
        error(node->getLine(), "constant expression required", "");
    }
}

// Both test, and if necessary spit out an error, to see if the node is really
// an integer.
void TParseContext::checkIsScalarInteger(TIntermTyped *node, const char *token)
{
    if (!node->isScalarInt())
    {
        error(node->getLine(), "integer expression required", token);
    }
}

// Both test, and if necessary spit out an error, to see if we are currently
// globally scoped.
bool TParseContext::checkIsAtGlobalLevel(const TSourceLoc &line, const char *token)
{
    if (!symbolTable.atGlobalLevel())
    {
        error(line, "only allowed at global scope", token);
        return false;
    }
    return true;
}

void TParseContext::checkIsValidExpressionStatement(const TSourceLoc &line, TIntermTyped *expr)
{
    if (expr->isInterfaceBlock())
    {
        error(line, "expression statement is not allowed for interface blocks", "");
    }
}

// ESSL 3.00.5 sections 3.8 and 3.9.
// If it starts "gl_" or contains two consecutive underscores, it's reserved.
// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a webgl shader.
bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const ImmutableString &identifier)
{
    static const char *reservedErrMsg = "reserved built-in name";
    if (gl::IsBuiltInName(identifier.data()))
    {
        error(line, reservedErrMsg, identifier);
        return false;
    }
    if (sh::IsWebGLBasedSpec(mShaderSpec))
    {
        if (identifier.beginsWith("webgl_") || identifier.beginsWith("_webgl_"))
        {
            error(line, reservedErrMsg, identifier);
            return false;
        }
    }
    if (identifier.contains("__"))
    {
        if (sh::IsWebGLBasedSpec(mShaderSpec))
        {
            error(line,
                  "identifiers containing two consecutive underscores (__) are reserved as "
                  "possible future keywords",
                  identifier);
            return false;
        }
        else
        {
            // Using double underscores is allowed, but may result in unintended behaviors, so a
            // warning is issued.
            // OpenGL ES Shader Language 3.2 specification:
            // > 3.7. Keywords
            // > ...
            // > In addition, all identifiers containing two consecutive underscores (__) are
            // > reserved for use by underlying software layers. Defining such a name in a shader
            // > does not itself result in an error, but may result in unintended behaviors that
            // > stem from having multiple definitions of the same name.
            warning(line,
                    "all identifiers containing two consecutive underscores (__) are reserved - "
                    "unintented behaviors are possible",
                    identifier.data());
        }
    }

    // Validate that identifier names won't conflict with the name hashing done later.
    // See https://crbug.com/499176133
    if (identifier.length() >= kMaxAvailableIdentifierLength && identifier[0] == '_' &&
        (identifier[1] == mResources.UserVariableNamePrefix ||
         identifier[1] == mResources.UserBlockNamePrefix))
    {
        std::string err = "identifiers beginning with `_` must be < " +
                          std::to_string(kMaxAvailableIdentifierLength) + " characters";
        error(line, err.c_str(), identifier);
        return false;
    }
    return true;
}

// Make sure the argument types are correct for constructing a specific type.
bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
                                              const TIntermSequence &arguments,
                                              const TType &type)
{
    if (arguments.empty())
    {
        error(line, "constructor does not have any arguments", "constructor");
        return false;
    }

    for (TIntermNode *arg : arguments)
    {
        markStaticUseIfSymbol(arg);
        const TIntermTyped *argTyped = arg->getAsTyped();
        ASSERT(argTyped != nullptr);
        if (IsOpaqueType(argTyped->getBasicType()))
        {
            std::string reason("cannot convert a variable with type ");
            reason += getBasicString(argTyped->getBasicType());
            error(line, reason.c_str(), "constructor");
            return false;
        }
        else if (argTyped->getType().isStructureContainingSamplers())
        {
            std::string reason("cannot convert a variable with struct type containing samplers");
            error(line, reason.c_str(), "constructor");
            return false;
        }
        else if (argTyped->getMemoryQualifier().writeonly)
        {
            error(line, "cannot convert a variable with writeonly", "constructor");
            return false;
        }
        if (argTyped->getBasicType() == EbtVoid)
        {
            error(line, "cannot convert a void", "constructor");
            return false;
        }
        else if (argTyped->getBasicType() == EbtYuvCscStandardEXT)
        {
            error(line, "cannot convert a yuvCscStandardEXT", "constructor");
            return false;
        }
    }

    if (type.isArray())
    {
        // The size of an unsized constructor should already have been determined.
        ASSERT(!type.isUnsizedArray());
        if (static_cast<size_t>(type.getOutermostArraySize()) != arguments.size())
        {
            error(line, "array constructor needs one argument per array element", "constructor");
            return false;
        }
        // GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of
        // the array.
        for (TIntermNode *const &argNode : arguments)
        {
            const TType &argType = argNode->getAsTyped()->getType();
            if (mShaderVersion < 310 && argType.isArray())
            {
                error(line, "constructing from a non-dereferenced array", "constructor");
                return false;
            }
            if (!argType.isElementTypeOf(type))
            {
                error(line, "Array constructor argument has an incorrect type", "constructor");
                return false;
            }
        }
    }
    else if (type.getBasicType() == EbtStruct)
    {
        const TFieldList &fields = type.getStruct()->fields();
        if (fields.size() != arguments.size())
        {
            error(line,
                  "Number of constructor parameters does not match the number of structure fields",
                  "constructor");
            return false;
        }

        for (size_t i = 0; i < fields.size(); i++)
        {
            if (i >= arguments.size() ||
                arguments[i]->getAsTyped()->getType() != *fields[i]->type())
            {
                error(line, "Structure constructor arguments do not match structure fields",
                      "constructor");
                return false;
            }
        }
    }
    else
    {
        // We're constructing a scalar, vector, or matrix.

        // Note: It's okay to have too many components available, but not okay to have unused
        // arguments. 'full' will go to true when enough args have been seen. If we loop again,
        // there is an extra argument, so 'overFull' will become true.

        size_t size    = 0;
        bool full      = false;
        bool overFull  = false;
        bool matrixArg = false;
        for (TIntermNode *arg : arguments)
        {
            const TIntermTyped *argTyped = arg->getAsTyped();
            ASSERT(argTyped != nullptr);

            if (argTyped->getBasicType() == EbtStruct)
            {
                error(line, "a struct cannot be used as a constructor argument for this type",
                      "constructor");
                return false;
            }
            if (argTyped->getBasicType() == EbtInterfaceBlock)
            {
                error(line,
                      "an interface block cannot be used as a constructor argument for this type",
                      "constructor");
                return false;
            }
            if (argTyped->getType().isArray())
            {
                error(line, "constructing from a non-dereferenced array", "constructor");
                return false;
            }
            if (argTyped->getType().isMatrix())
            {
                matrixArg = true;
            }

            size += argTyped->getType().getObjectSize();
            if (full)
            {
                overFull = true;
            }
            if (size >= type.getObjectSize())
            {
                full = true;
            }
        }

        if (type.isMatrix() && matrixArg)
        {
            if (arguments.size() != 1)
            {
                error(line, "constructing matrix from matrix can only take one argument",
                      "constructor");
                return false;
            }
        }
        else
        {
            if (size != 1 && size < type.getObjectSize())
            {
                error(line, "not enough data provided for construction", "constructor");
                return false;
            }
            if (overFull)
            {
                error(line, "too many arguments", "constructor");
                return false;
            }
        }
    }

    return true;
}

// This function checks to see if a void variable has been declared and raise an error message for
// such a case
//
// returns true in case of an error
//
bool TParseContext::checkIsNonVoid(const TSourceLoc &line,
                                   const ImmutableString &identifier,
                                   const TBasicType &type)
{
    if (type == EbtVoid)
    {
        error(line, "illegal use of type 'void'", identifier);
        return false;
    }

    return true;
}

// This function checks to see if the node (for the expression) contains a scalar boolean expression
// or not.
bool TParseContext::checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type)
{
    if (type->getBasicType() != EbtBool || !type->isScalar())
    {
        error(line, "boolean expression expected", "");
        return false;
    }
    return true;
}

// This function checks to see if the node (for the expression) contains a scalar boolean expression
// or not.
void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType)
{
    if (pType.getBasicType() != EbtBool || pType.isAggregate())
    {
        error(line, "boolean expression expected", "");
    }
}

bool TParseContext::checkIsNotOpaqueType(const TSourceLoc &line,
                                         const TTypeSpecifierNonArray &pType,
                                         const char *reason)
{
    if (pType.type == EbtStruct)
    {
        if (ContainsOpaque<IsSamplerFunc>(pType.userDef))
        {
            std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
            reasonStream << reason << " (structure contains a sampler)";
            std::string reasonStr = reasonStream.str();
            error(line, reasonStr.c_str(), getBasicString(pType.type));
            return false;
        }
        // only samplers need to be checked from structs, since other opaque types can't be struct
        // members.
        return true;
    }
    else if (IsOpaqueType(pType.type))
    {
        error(line, reason, getBasicString(pType.type));
        return false;
    }

    return true;
}

void TParseContext::checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line,
                                                          const TPublicType &pType)
{
    if (pType.layoutQualifier.location != -1)
    {
        error(line, "location must only be specified for a single input or output variable",
              "location");
    }
}

void TParseContext::checkLocationIsNotSpecified(const TSourceLoc &location,
                                                const TLayoutQualifier &layoutQualifier)
{
    if (layoutQualifier.location != -1)
    {
        const char *errorMsg = "invalid layout qualifier: only valid on program inputs and outputs";
        if (mShaderVersion >= 310)
        {
            errorMsg =
                "invalid layout qualifier: only valid on shader inputs, outputs, and uniforms";
        }
        error(location, errorMsg, "location");
    }
}

void TParseContext::checkStd430IsForShaderStorageBlock(const TSourceLoc &location,
                                                       const TLayoutBlockStorage &blockStorage,
                                                       const TQualifier &qualifier)
{
    if (blockStorage == EbsStd430 && qualifier != EvqBuffer)
    {
        error(location, "The std430 layout is supported only for shader storage blocks.", "std430");
    }
}

// Do size checking for an array type's size.
unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr)
{
    TIntermConstantUnion *constant = expr->getAsConstantUnion();

    // ANGLE should be able to fold any EvqConst expressions resulting in an integer - but to be
    // safe against corner cases we still check for constant folding. Some interpretations of the
    // spec have allowed constant expressions with side effects - like array length() method on a
    // non-constant array.
    if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt())
    {
        error(line, "array size must be a constant integer expression", "");
        return 1u;
    }

    unsigned int size = 0u;

    if (constant->getBasicType() == EbtUInt)
    {
        size = constant->getUConst(0);
    }
    else
    {
        int signedSize = constant->getIConst(0);

        if (signedSize < 0)
        {
            error(line, "array size must be non-negative", "");
            return 1u;
        }

        size = static_cast<unsigned int>(signedSize);
    }

#ifdef ANGLE_IR
    if (mCompileOptions.useIR)
    {
        // Pop the array size from the IR too.  IR's evaluation should be equal to the AST constant
        // fold; when the AST goes away, the size as evaluated by IR is going to be used.
        const uint32_t sizeAccordingToIr = mIRBuilder.popArraySize();
        ASSERT(mDiagnostics->numErrors() != 0 || size == sizeAccordingToIr);
    }
#endif

    if (size == 0u)
    {
        error(line, "array size must be greater than zero", "");
        return 1u;
    }

    return size;
}

bool TParseContext::checkIsValidArrayDimension(const TSourceLoc &line,
                                               TVector<unsigned int> *arraySizes)
{
    if (mCompileOptions.limitExpressionComplexity &&
        arraySizes->size() > static_cast<size_t>(mResources.MaxExpressionComplexity))
    {
        error(line, "array has too many dimensions", "");
        return false;
    }
    return true;
}

// See if this qualifier can be an array.
bool TParseContext::checkIsValidQualifierForArray(const TSourceLoc &line,
                                                  const TPublicType &elementQualifier)
{
    if ((elementQualifier.qualifier == EvqAttribute) ||
        (elementQualifier.qualifier == EvqVertexIn) ||
        (elementQualifier.qualifier == EvqConst && mShaderVersion < 300))
    {
        error(line, "cannot declare arrays of this qualifier",
              TType(elementQualifier).getQualifierString());
        return false;
    }

    return true;
}

// See if this element type can be formed into an array.
bool TParseContext::checkArrayElementIsNotArray(const TSourceLoc &line,
                                                const TPublicType &elementType)
{
    if (mShaderVersion < 310 && elementType.isArray())
    {
        TInfoSinkBase typeString;
        typeString << TType(elementType);
        error(line, "cannot declare arrays of arrays", typeString.c_str());
        return false;
    }
    return true;
}

// Check for array-of-arrays being used as non-allowed shader inputs/outputs.
bool TParseContext::checkArrayOfArraysInOut(const TSourceLoc &line,
                                            const TPublicType &elementType,
                                            const TType &arrayType)
{
    if (arrayType.isArrayOfArrays())
    {
        if (elementType.qualifier == EvqVertexOut)
        {
            error(line, "vertex shader output cannot be an array of arrays",
                  TType(elementType).getQualifierString());
            return false;
        }
        if (elementType.qualifier == EvqFragmentIn)
        {
            error(line, "fragment shader input cannot be an array of arrays",
                  TType(elementType).getQualifierString());
            return false;
        }
        if (elementType.qualifier == EvqFragmentOut || elementType.qualifier == EvqFragmentInOut)
        {
            error(line, "fragment shader output cannot be an array of arrays",
                  TType(elementType).getQualifierString());
            return false;
        }
    }
    return true;
}

// Check if this qualified element type can be formed into an array. This is only called when array
// brackets are associated with an identifier in a declaration, like this:
//   float a[2];
// Similar checks are done in addFullySpecifiedType for array declarations where the array brackets
// are associated with the type, like this:
//   float[2] a;
bool TParseContext::checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation,
                                                         const TPublicType &elementType)
{
    if (!checkArrayElementIsNotArray(indexLocation, elementType))
    {
        return false;
    }
    // In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere.
    // In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section
    // 4.3.4).
    // Geometry shader requires each user-defined input be declared as arrays or inside input
    // blocks declared as arrays (GL_EXT_geometry_shader section 11.1gs.4.3). For the purposes of
    // interface matching, such variables and blocks are treated as though they were not declared
    // as arrays (GL_EXT_geometry_shader section 7.4.1).
    if (mShaderVersion >= 300 && elementType.getBasicType() == EbtStruct &&
        sh::IsVarying(elementType.qualifier) &&
        !IsGeometryShaderInput(mShaderType, elementType.qualifier) &&
        !IsTessellationControlShaderInput(mShaderType, elementType.qualifier) &&
        !IsTessellationEvaluationShaderInput(mShaderType, elementType.qualifier) &&
        !IsTessellationControlShaderOutput(mShaderType, elementType.qualifier))
    {
        TInfoSinkBase typeString;
        typeString << TType(elementType);
        error(indexLocation, "cannot declare arrays of structs of this qualifier",
              typeString.c_str());
        return false;
    }
    return checkIsValidQualifierForArray(indexLocation, elementType);
}

void TParseContext::checkNestingLevel(const TSourceLoc &line)
{
    if (mControlFlow.size() > static_cast<size_t>(mResources.MaxStatementDepth))
    {
        error(line, "statement is too deeply nested", "");
    }
}

// Enforce non-initializer type/qualifier rules.
void TParseContext::checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
                                                         const ImmutableString &identifier,
                                                         TType *type)
{
    ASSERT(type != nullptr);
    if (type->getQualifier() == EvqConst)
    {
        // Make the qualifier make sense.
        type->setQualifier(EvqTemporary);

        // Generate informative error messages for ESSL1.
        // In ESSL3 arrays and structures containing arrays can be constant.
        if (mShaderVersion < 300 && type->isStructureContainingArrays())
        {
            error(line,
                  "structures containing arrays may not be declared constant since they cannot be "
                  "initialized",
                  identifier);
        }
        else
        {
            error(line, "variables with qualifier 'const' must be initialized", identifier);
        }
    }
}

void TParseContext::checkDeclarationIsValidArraySize(const TSourceLoc &line,
                                                     const ImmutableString &identifier,
                                                     TType *type)
{

    // Implicitly declared arrays are only allowed with tessellation or geometry shader inputs
    if (type->isUnsizedArray() &&
        ((mShaderType != GL_TESS_CONTROL_SHADER && mShaderType != GL_TESS_EVALUATION_SHADER &&
          mShaderType != GL_GEOMETRY_SHADER) ||
         (mShaderType == GL_GEOMETRY_SHADER && type->getQualifier() == EvqGeometryOut)))
    {
        error(line,
              "implicitly sized arrays only allowed for tessellation shaders "
              "or geometry shader inputs",
              identifier);
    }
}

bool TParseContext::checkVariableSize(const TSourceLoc &line,
                                      const ImmutableString &identifier,
                                      const TType *type)
{
    // Prevent unrealistically large variable sizes in shaders.  This works around driver bugs
    // around int-size limits (such as 2GB).  The limits are generously large enough that no real
    // shader should ever hit it.
    //
    // The size check does not take std430 into account as it is intended for WebGL shaders.  For
    // the same reason, other shader stages than vertex/fragment/compute are ignored as defer-sized
    // variables e.g. in geometry shaders are not handled.
    if (!mCompileOptions.rejectWebglShadersWithLargeVariables ||
        (mShaderType != GL_VERTEX_SHADER && mShaderType != GL_FRAGMENT_SHADER &&
         mShaderType != GL_COMPUTE_SHADER))
    {
        return true;
    }

    // Check the cache of validated types first.
    size_t variableSize   = 0;
    auto preValidatedIter = mValidatedVariableTypeSizes.find(*type);
    if (preValidatedIter != mValidatedVariableTypeSizes.end())
    {
        variableSize = preValidatedIter->second;
    }
    else
    {
        // Note: the only allowed interface block in webgl shaders is UBOs in std140 mode, so the
        // size is unconditionally calculated with std140 rules if the variable is an interface
        // block. Uniform variables are treated the same way as UBOs, as they are often packed the
        // same way later on.
        variableSize = CalculateVariableSize(
                           type, type->isInterfaceBlock() || type->getQualifier() == EvqUniform)
                           .ValueOrDefault(std::numeric_limits<size_t>::max());

        mValidatedVariableTypeSizes[*type] = variableSize;
    }

    if (variableSize > kWebGLMaxVariableSizeInBytes)
    {
        error(line, "Size of declared variable exceeds implementation-defined limit", identifier);
        return false;
    }

    switch (type->getQualifier())
    {
        // List of all types that need to be limited (for example because they cause overflows
        // in drivers, or create trouble for the SPIR-V gen as the number of an instruction's
        // arguments cannot be more than 64KB (see OutputSPIRVTraverser::cast)).

        // Local/global variables
        case EvqTemporary:
        case EvqGlobal:
        case EvqConst:

        // Function arguments
        case EvqParamIn:
        case EvqParamOut:
        case EvqParamInOut:
        case EvqParamConst:

        // Varyings
        case EvqVaryingIn:
        case EvqVaryingOut:
        case EvqSmoothOut:
        case EvqFlatOut:
        case EvqNoPerspectiveOut:
        case EvqCentroidOut:
        case EvqSampleOut:
        case EvqNoPerspectiveCentroidOut:
        case EvqNoPerspectiveSampleOut:
        case EvqSmoothIn:
        case EvqFlatIn:
        case EvqNoPerspectiveIn:
        case EvqCentroidIn:
        case EvqNoPerspectiveCentroidIn:
        case EvqNoPerspectiveSampleIn:
        case EvqVertexOut:
        case EvqFragmentIn:
        case EvqPerVertexIn:
        case EvqPerVertexOut:

            if (variableSize > kWebGLMaxPrivateVariableSizeInBytes)
            {
                error(line,
                      "Size of declared private variable exceeds implementation-defined limit",
                      identifier);
                return false;
            }
            mTotalPrivateVariablesSize += variableSize;
            break;
        default:
            break;
    }

    return true;
}

void TParseContext::checkVaryingLocations(const TSourceLoc &line, const TVariable *variable)
{
    // This function only checks those varyings with explicit locations for the purposes of conflict
    // detection.
    const TType &type = variable->getType();
    if (type.getLayoutQualifier().location == -1)
    {
        return;
    }

    const bool isVaryingIn  = IsVaryingIn(type.getQualifier());
    const bool isVaryingOut = IsVaryingOut(type.getQualifier());
    if (!isVaryingIn && !isVaryingOut)
    {
        return;
    }

    VariableAndField conflictingSymbol;
    const TField *conflictingFieldInNewSymbol = nullptr;

    if (!ValidateVaryingLocation(variable,
                                 isVaryingIn ? &mInputVaryingLocations : &mOutputVaryingLocations,
                                 mShaderType, &conflictingSymbol, &conflictingFieldInNewSymbol))
    {
        std::stringstream strstr = sh::InitializeStream<std::stringstream>();
        strstr << "'" << variable->name();
        if (conflictingFieldInNewSymbol != nullptr)
        {
            strstr << "." << conflictingFieldInNewSymbol->name();
        }
        strstr << "' conflicting location with '" << conflictingSymbol.variable->name();
        if (conflictingSymbol.field)
        {
            strstr << "." << conflictingSymbol.field->name();
        }
        strstr << "'";
        error(line, strstr.str().c_str(), variable->name());
    }
}

void TParseContext::checkFragmentOutputLocations(const TSourceLoc &line, const TVariable *variable)
{
    const TType &type                       = variable->getType();
    const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier();
    if (type.getQualifier() != EvqFragmentOut && type.getQualifier() != EvqFragmentInOut)
    {
        return;
    }

    VariableAndLocation fragmentOutput;
    fragmentOutput.line     = line;
    fragmentOutput.variable = variable;

    // Keep track of the variables for conflict check at the end.  In particular, the limit check
    // and error messages should use either |MAX_DRAW_BUFFERS| or |MAX_DUAL_SOURCE_DRAW_BUFFERS|,
    // and that depends on whether |index=1| is used by any declaration.
    if (layoutQualifier.location != -1)
    {
        mFragmentOutputsWithLocation.push_back(fragmentOutput);
        if (layoutQualifier.index == 1)
        {
            mFragmentOutputIndex1Used = true;
        }
    }
    else if (layoutQualifier.yuv == true)
    {
        mFragmentOutputsYuv.push_back(fragmentOutput);
    }
    else
    {
        mFragmentOutputsWithoutLocation.push_back(fragmentOutput);
    }
}

void TParseContext::checkVariableLocations(const TSourceLoc &line, const TVariable *variable)
{
    // Interface variables cannot be declared inside functions.
    if (mCurrentFunction != nullptr || variable->symbolType() == SymbolType::Empty)
    {
        return;
    }

    // In ESSL 310, the shader may assign explicit locations to varyings, which need to be checked
    // for conflicts.
    if (mShaderVersion >= 310)
    {
        checkVaryingLocations(line, variable);
    }

    // In ESSL 300, the shader may assign explicit locations to fragment outputs, which need to be
    // checked for conflicts.
    if (mShaderVersion >= 300 && mShaderType == GL_FRAGMENT_SHADER)
    {
        checkFragmentOutputLocations(line, variable);
    }
}

// Do some simple checks that are shared between all variable declarations,
// and update the symbol table.
//
// Returns true if declaring the variable succeeded.
//
bool TParseContext::declareVariable(const TSourceLoc &line,
                                    const ImmutableString &identifier,
                                    const TType *declarationType,
                                    GeomTessArray sized,
                                    TVariable **variable)
{
    ASSERT(*variable == nullptr);

    // When gl_Position and gl_PointSize are redeclared per EXT_separate_shader_objects, make sure
    // they have the right qualifier.
    const TType *type = declarationType;
    if (identifier == "gl_Position" || identifier == "gl_PointSize")
    {
        TType *fixedType = new TType(*type);
        fixedType->setQualifier(identifier == "gl_Position" ? EvqPosition : EvqPointSize);
        fixedType->setTypeId(type->typeId());
        type = fixedType;
    }

    SymbolType symbolType = SymbolType::UserDefined;
    switch (type->getQualifier())
    {
        case EvqPosition:
        case EvqPointSize:
        case EvqClipDistance:
        case EvqCullDistance:
        case EvqFragDepth:
        case EvqLastFragData:
        case EvqLastFragColor:
        case EvqLastFragDepth:
        case EvqLastFragStencil:
            symbolType = SymbolType::BuiltIn;

            if (mBuiltInQualified[type->getQualifier()])
            {
                error(
                    line,
                    "built-ins cannot be redeclared after being qualified as invariant or precise",
                    identifier);
            }
            break;
        default:
            break;
    }

    *variable = new TVariable(&symbolTable, identifier, type, symbolType);

    if (type->getQualifier() == EvqFragmentOut)
    {
        if (type->getLayoutQualifier().index != -1 && type->getLayoutQualifier().location == -1)
        {
            error(line,
                  "If index layout qualifier is specified for a fragment output, location must "
                  "also be specified.",
                  "index");
            return false;
        }
    }
    else
    {
        checkIndexIsNotSpecified(line, type->getLayoutQualifier().index);
    }

    if (!((identifier.beginsWith("gl_LastFragData") || type->getQualifier() == EvqFragmentInOut) &&
          (isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch) ||
           isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch_non_coherent))) &&
        !(type->isPixelLocal() && isExtensionEnabled(TExtension::ANGLE_shader_pixel_local_storage)))
    {
        checkNoncoherentIsNotSpecified(line, type->getLayoutQualifier().noncoherent);
    }
    else if (isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch_non_coherent) &&
             !isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch))
    {
        checkNoncoherentIsSpecified(line, type->getLayoutQualifier().noncoherent);
    }

    checkBindingIsValid(line, *type);

    bool needsReservedCheck = true;
    const TVariable *builtInSymbol =
        static_cast<const TVariable *>(symbolTable.findBuiltIn(identifier, mShaderVersion));

    // Some built-ins may be redeclared with a new precision qualifier, but must otherwise match the
    // built-in in type, array dimensions etc: gl_LastFragData, gl_LastFragColorARM,
    // gl_LastFragDepthARM, gl_LastFragStencilARM, gl_ClipDistance, gl_CullDistance, gl_FragDepth,
    // gl_Position, gl_PointSize.
    //
    // For gl_ClipDistance and gl_CullDistance, the array size can be less than the built-in's.
    if (builtInSymbol != nullptr)
    {
        const TType &expectedType = builtInSymbol->getType();

        uint32_t expectedArraySize         = 0;
        bool canArraySizeBeLessThanBuiltIn = false;
        const char *arraySizeCheckError    = nullptr;

        switch (expectedType.getQualifier())
        {
            case EvqLastFragData:
                expectedArraySize = static_cast<const TVariable *>(
                                        symbolTable.findBuiltIn(
                                            ImmutableString("gl_MaxDrawBuffers"), mShaderVersion))
                                        ->getConstPointer()
                                        ->getIConst();
                arraySizeCheckError =
                    "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers";
                needsReservedCheck = !checkCanUseOneOfExtensions(line, builtInSymbol->extensions());
                break;
            case EvqLastFragColor:
            case EvqLastFragDepth:
            case EvqLastFragStencil:
                needsReservedCheck = !checkCanUseOneOfExtensions(line, builtInSymbol->extensions());
                break;
            case EvqClipDistance:
            {
                const TVariable *maxClipDistances =
                    static_cast<const TVariable *>(symbolTable.findBuiltIn(
                        ImmutableString("gl_MaxClipDistances"), mShaderVersion));
                if (maxClipDistances != nullptr)
                {
                    expectedArraySize = maxClipDistances->getConstPointer()->getIConst();
                    canArraySizeBeLessThanBuiltIn = true;
                    arraySizeCheckError =
                        "redeclaration of gl_ClipDistance with size > gl_MaxClipDistances";
                    needsReservedCheck =
                        !checkCanUseOneOfExtensions(line, builtInSymbol->extensions());
                }
                else
                {
                    // Unsupported extension
                    error(line, "redeclaration of built-in is not allowed", identifier);
                    return false;
                }
                break;
            }
            case EvqCullDistance:
            {
                const TVariable *maxCullDistances =
                    static_cast<const TVariable *>(symbolTable.findBuiltIn(
                        ImmutableString("gl_MaxCullDistances"), mShaderVersion));
                if (maxCullDistances != nullptr)
                {
                    expectedArraySize = maxCullDistances->getConstPointer()->getIConst();
                    canArraySizeBeLessThanBuiltIn = true;
                    arraySizeCheckError =
                        "redeclaration of gl_CullDistance with size > gl_MaxCullDistances";
                    needsReservedCheck =
                        !checkCanUseOneOfExtensions(line, builtInSymbol->extensions());
                }
                else
                {
                    // Unsupported extension
                    error(line, "redeclaration of built-in is not allowed", identifier);
                    return false;
                }
                break;
            }
            case EvqFragDepth:
                needsReservedCheck = !isExtensionEnabled(TExtension::EXT_conservative_depth) ||
                                     mShaderType != GL_FRAGMENT_SHADER ||
                                     symbolType == SymbolType::UserDefined;
                break;
            case EvqPosition:
            case EvqPointSize:
                if (isExtensionEnabled(TExtension::EXT_separate_shader_objects) &&
                    mShaderType == GL_VERTEX_SHADER)
                {
                    needsReservedCheck = false;
                    if (expectedType.getQualifier() == EvqPosition)
                    {
                        mPositionRedeclaredForSeparateShaderObject = true;
                    }
                    else
                    {
                        mPointSizeRedeclaredForSeparateShaderObject = true;
                    }
                    if (mPositionOrPointSizeUsedForSeparateShaderObject)
                    {
                        error(line,
                              "When EXT_separate_shader_objects is enabled, both gl_Position and "
                              "gl_PointSize must be redeclared before either is used",
                              identifier);
                    }
                }
                else
                {
                    error(line, "redeclaration of built-in is not allowed", identifier);
                    return false;
                }
                break;
            default:
                error(line, "reserved built-in name", identifier);
                return false;
        }

        // No built-in is an array of arrays.
        if (type->isArrayOfArrays())
        {
            error(line, "redeclaration of built-in as an array of arrays", identifier);
            return false;
        }

        if (type->getBasicType() != expectedType.getBasicType() ||
            type->getNominalSize() != expectedType.getNominalSize() ||
            type->getSecondarySize() != expectedType.getSecondarySize() ||
            type->isArray() != expectedType.isArray())
        {
            error(line, "redeclaration of built-in with a different type", identifier);
            return false;
        }

        if (type->isArray())
        {
            unsigned int arraySize = type->getOutermostArraySize();
            if (arraySize > expectedArraySize ||
                (!canArraySizeBeLessThanBuiltIn && arraySize != expectedArraySize))
            {
                error(line, arraySizeCheckError, identifier);
                return false;
            }
        }

        switch (expectedType.getQualifier())
        {
            case EvqClipDistance:
                MarkClipCullRedeclaredSize(line, type->getOutermostArraySize(), &mClipDistanceInfo);
                break;
            case EvqCullDistance:
                MarkClipCullRedeclaredSize(line, type->getOutermostArraySize(), &mCullDistanceInfo);
                break;
            default:
                break;
        }
    }

    if (needsReservedCheck && !checkIsNotReserved(line, identifier))
    {
        return false;
    }

    if (!symbolTable.declare(*variable))
    {
        error(line, "redefinition", identifier);
        return false;
    }

    if (!checkIsNonVoid(line, identifier, type->getBasicType()))
    {
        return false;
    }

    if (!checkVariableSize(line, identifier, type))
    {
        return false;
    }
    checkVariableLocations(line, *variable);

    // Declare the variable in IR
    declareIRVariable(*variable, sized);

    return true;
}

void TParseContext::declareIRVariable(const TVariable *variable, GeomTessArray sized)
{
    // If the variable is yet to be sized, don't declare it yet.
    if (sized == GeomTessArray::Deferred)
    {
        mDeferredArrayVariablesToSize.push_back(variable);
        return;
    }

    const TType &type = variable->getType();
    ASSERT(type.isTypeIdSet());

    ir::VariableId variableId;
    switch (type.getQualifier())
    {
        case EvqTemporary:
        case EvqGlobal:
        case EvqConst:
        case EvqParamIn:
        case EvqParamOut:
        case EvqParamInOut:
        case EvqParamConst:
            // Temporary variables
            variableId = mIRBuilder.declareTempVariable(variable->name(), type.typeId(), type);
            break;
        default:
            // Interface and built-in variables
            variableId = mIRBuilder.declareInterfaceVariable(
                variable->symbolType() == SymbolType::Empty ? kEmptyImmutableString
                                                            : variable->name(),
                type.typeId(), type, ir::DeclarationSource::Shader);
            break;
    }
    mVariableToId[variable] = VariableToIdInfo{variableId, VariableToIdInfo::kNoImplicitField};
}

void TParseContext::parseParameterQualifier(const TSourceLoc &line,
                                            const TTypeQualifierBuilder &typeQualifierBuilder,
                                            TPublicType &type)
{
    // The only parameter qualifiers a parameter can have are in, out, inout or const.
    TTypeQualifier typeQualifier =
        typeQualifierBuilder.getParameterTypeQualifier(type.getBasicType(), mDiagnostics);

    if (typeQualifier.qualifier == EvqParamOut || typeQualifier.qualifier == EvqParamInOut)
    {
        if (IsOpaqueType(type.getBasicType()))
        {
            error(line, "opaque types cannot be output parameters", type.getBasicString());
        }
    }

    if (!IsImage(type.getBasicType()))
    {
        checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, line);
    }
    else
    {
        type.setMemoryQualifier(typeQualifier.memoryQualifier);
    }

    type.setQualifier(typeQualifier.qualifier);

    if (typeQualifier.precision != EbpUndefined)
    {
        type.setPrecision(typeQualifier.precision);
    }

    if (typeQualifier.precise)
    {
        type.setPrecise(true);
    }
}

void TParseContext::addParameter(TFunction *function, TParameter *param)
{
    const TVariable *variable = param->createVariable(&symbolTable);
    function->addParameter(variable);
}

template <size_t size>
bool TParseContext::checkCanUseOneOfExtensions(const TSourceLoc &line,
                                               const std::array<TExtension, size> &extensions)
{
    ASSERT(!extensions.empty());
    const TExtensionBehavior &extBehavior = extensionBehavior();

    bool canUseWithWarning    = false;
    bool canUseWithoutWarning = false;

    const char *errorMsgString   = "";
    TExtension errorMsgExtension = TExtension::UNDEFINED;

    for (TExtension extension : extensions)
    {
        auto extIter = extBehavior.find(extension);
        if (canUseWithWarning)
        {
            // We already have an extension that we can use, but with a warning.
            // See if we can use the alternative extension without a warning.
            if (extIter == extBehavior.end())
            {
                continue;
            }
            if (extIter->second == EBhEnable || extIter->second == EBhRequire)
            {
                canUseWithoutWarning = true;
                break;
            }
            continue;
        }
        if (extension == TExtension::UNDEFINED)
        {
            continue;
        }
        else if (extIter == extBehavior.end())
        {
            errorMsgString    = "extension is not supported";
            errorMsgExtension = extension;
        }
        else if (extIter->second == EBhUndefined || extIter->second == EBhDisable)
        {
            errorMsgString    = "extension is disabled";
            errorMsgExtension = extension;
        }
        else if (extIter->second == EBhWarn)
        {
            errorMsgExtension = extension;
            canUseWithWarning = true;
        }
        else
        {
            ASSERT(extIter->second == EBhEnable || extIter->second == EBhRequire);
            canUseWithoutWarning = true;
            break;
        }
    }

    if (canUseWithoutWarning)
    {
        return true;
    }
    if (canUseWithWarning)
    {
        warning(line, "extension is being used", GetExtensionNameString(errorMsgExtension));
        return true;
    }
    error(line, errorMsgString, GetExtensionNameString(errorMsgExtension));
    return false;
}

template bool TParseContext::checkCanUseOneOfExtensions(
    const TSourceLoc &line,
    const std::array<TExtension, 1> &extensions);
template bool TParseContext::checkCanUseOneOfExtensions(
    const TSourceLoc &line,
    const std::array<TExtension, 2> &extensions);
template bool TParseContext::checkCanUseOneOfExtensions(
    const TSourceLoc &line,
    const std::array<TExtension, 3> &extensions);

bool TParseContext::checkCanUseExtension(const TSourceLoc &line, TExtension extension)
{
    ASSERT(extension != TExtension::UNDEFINED);
    return checkCanUseOneOfExtensions(line, std::array<TExtension, 1u>{{extension}});
}

// ESSL 3.00.6 section 4.8 Empty Declarations: "The combinations of qualifiers that cause
// compile-time or link-time errors are the same whether or not the declaration is empty".
// This function implements all the checks that are done on qualifiers regardless of if the
// declaration is empty.
void TParseContext::declarationQualifierErrorCheck(const sh::TQualifier qualifier,
                                                   const sh::TLayoutQualifier &layoutQualifier,
                                                   const TSourceLoc &location)
{
    if (qualifier == EvqShared && !layoutQualifier.isEmpty())
    {
        error(location, "Shared memory declarations cannot have layout specified", "layout");
    }

    if (layoutQualifier.matrixPacking != EmpUnspecified)
    {
        error(location, "layout qualifier only valid for interface blocks",
              getMatrixPackingString(layoutQualifier.matrixPacking));
        return;
    }

    if (layoutQualifier.blockStorage != EbsUnspecified)
    {
        error(location, "layout qualifier only valid for interface blocks",
              getBlockStorageString(layoutQualifier.blockStorage));
        return;
    }

    if (qualifier != EvqFragDepth)
    {
        checkDepthIsNotSpecified(location, layoutQualifier.depth);
    }

    if (qualifier == EvqFragmentOut)
    {
        if (layoutQualifier.location != -1 && layoutQualifier.yuv == true)
        {
            error(location, "invalid layout qualifier combination", "yuv");
            return;
        }
    }
    else
    {
        checkYuvIsNotSpecified(location, layoutQualifier.yuv);
    }

    if (qualifier != EvqFragmentIn)
    {
        checkEarlyFragmentTestsIsNotSpecified(location, layoutQualifier.earlyFragmentTests);
    }

    // If multiview extension is enabled, "in" qualifier is allowed in the vertex shader in previous
    // parsing steps. So it needs to be checked here.
    if (anyMultiviewExtensionAvailable() && mShaderVersion < 300 && qualifier == EvqVertexIn)
    {
        error(location, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
    }

    bool canHaveLocation = qualifier == EvqVertexIn || qualifier == EvqFragmentOut;
    if (mShaderVersion >= 300 &&
        (isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch) ||
         isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch_non_coherent)))
    {
        // In the case of EXT_shader_framebuffer_fetch or EXT_shader_framebuffer_fetch_non_coherent
        // extension, the location of inout qualifier is used to set the input attachment index
        canHaveLocation = canHaveLocation || qualifier == EvqFragmentInOut;
    }
    if (mShaderVersion >= 310)
    {
        canHaveLocation = canHaveLocation || qualifier == EvqUniform || IsVarying(qualifier);
        // We're not checking whether the uniform location is in range here since that depends on
        // the type of the variable.
        // The type can only be fully determined for non-empty declarations.
    }
    if (!canHaveLocation)
    {
        checkLocationIsNotSpecified(location, layoutQualifier);
    }
}

void TParseContext::atomicCounterQualifierErrorCheck(const TPublicType &publicType,
                                                     const TSourceLoc &location)
{
    if (publicType.precision != EbpHigh)
    {
        error(location, "Can only be highp", "atomic counter");
    }
    // dEQP enforces compile error if location is specified. See uniform_location.test.
    if (publicType.layoutQualifier.location != -1)
    {
        error(location, "location must not be set for atomic_uint", "layout");
    }
    if (publicType.layoutQualifier.binding == -1)
    {
        error(location, "no binding specified", "atomic counter");
    }
}

void TParseContext::emptyDeclarationErrorCheck(const TType &type, const TSourceLoc &location)
{
    if (type.isUnsizedArray())
    {
        // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an
        // error. It is assumed that this applies to empty declarations as well.
        error(location, "empty array declaration needs to specify a size", "");
    }

    if (type.getQualifier() != EvqFragmentOut)
    {
        checkIndexIsNotSpecified(location, type.getLayoutQualifier().index);
    }
}

// These checks are done for all declarations that are non-empty. They're done for non-empty
// declarations starting a declarator list, and declarators that follow an empty declaration.
void TParseContext::nonEmptyDeclarationErrorCheck(const TPublicType &publicType,
                                                  const TSourceLoc &identifierLocation)
{
    switch (publicType.qualifier)
    {
        case EvqVaryingIn:
        case EvqVaryingOut:
        case EvqAttribute:
        case EvqVertexIn:
        case EvqFragmentOut:
        case EvqFragmentInOut:
        case EvqComputeIn:
            if (publicType.getBasicType() == EbtStruct)
            {
                error(identifierLocation, "cannot be used with a structure",
                      getQualifierString(publicType.qualifier));
                return;
            }
            break;
        case EvqBuffer:
            if (publicType.getBasicType() != EbtInterfaceBlock)
            {
                error(identifierLocation,
                      "cannot declare buffer variables at global scope(outside a block)",
                      getQualifierString(publicType.qualifier));
                return;
            }
            break;
        default:
            break;
    }
    std::string reason(getBasicString(publicType.getBasicType()));
    reason += "s must be uniform";
    if (publicType.qualifier != EvqUniform &&
        !checkIsNotOpaqueType(identifierLocation, publicType.typeSpecifierNonArray, reason.c_str()))
    {
        return;
    }

    if ((publicType.qualifier != EvqTemporary && publicType.qualifier != EvqGlobal &&
         publicType.qualifier != EvqConst) &&
        publicType.getBasicType() == EbtYuvCscStandardEXT)
    {
        error(identifierLocation, "cannot be used with a yuvCscStandardEXT",
              getQualifierString(publicType.qualifier));
        return;
    }

    if (mShaderVersion >= 310 && publicType.qualifier == EvqUniform)
    {
        // Valid uniform declarations can't be unsized arrays since uniforms can't be initialized.
        // But invalid shaders may still reach here with an unsized array declaration.
        TType type(publicType);
        if (!type.isUnsizedArray())
        {
            checkUniformLocationInRange(identifierLocation, type.getLocationCount(),
                                        publicType.layoutQualifier);
        }
    }

    if (mShaderVersion >= 300 && publicType.qualifier == EvqVertexIn)
    {
        // Valid vertex input declarations can't be unsized arrays since they can't be initialized.
        // But invalid shaders may still reach here with an unsized array declaration.
        TType type(publicType);
        if (!type.isUnsizedArray())
        {
            checkAttributeLocationInRange(identifierLocation, type.getLocationCount(),
                                          publicType.layoutQualifier);
        }
    }

    // check for layout qualifier issues
    const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;

    if (IsImage(publicType.getBasicType()))
    {

        switch (layoutQualifier.imageInternalFormat)
        {
            case EiifRGBA32F:
            case EiifRGBA16F:
            case EiifR32F:
            case EiifRGBA8:
            case EiifRGBA8_SNORM:
                if (!IsFloatImage(publicType.getBasicType()))
                {
                    error(identifierLocation,
                          "internal image format requires a floating image type",
                          getBasicString(publicType.getBasicType()));
                    return;
                }
                break;
            case EiifRGBA32I:
            case EiifRGBA16I:
            case EiifRGBA8I:
            case EiifR32I:
                if (!IsIntegerImage(publicType.getBasicType()))
                {
                    error(identifierLocation,
                          "internal image format requires an integer image type",
                          getBasicString(publicType.getBasicType()));
                    return;
                }
                break;
            case EiifRGBA32UI:
            case EiifRGBA16UI:
            case EiifRGBA8UI:
            case EiifR32UI:
                if (!IsUnsignedImage(publicType.getBasicType()))
                {
                    error(identifierLocation,
                          "internal image format requires an unsigned image type",
                          getBasicString(publicType.getBasicType()));
                    return;
                }
                break;
            case EiifUnspecified:
                error(identifierLocation, "layout qualifier", "No image internal format specified");
                return;
            default:
                error(identifierLocation, "layout qualifier", "unrecognized token");
                return;
        }

        // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
        switch (layoutQualifier.imageInternalFormat)
        {
            case EiifR32F:
            case EiifR32I:
            case EiifR32UI:
                break;
            default:
                if (!publicType.memoryQualifier.readonly && !publicType.memoryQualifier.writeonly)
                {
                    error(identifierLocation, "layout qualifier",
                          "Except for images with the r32f, r32i and r32ui format qualifiers, "
                          "image variables must be qualified readonly and/or writeonly");
                    return;
                }
                break;
        }
    }
    else if (IsPixelLocal(publicType.getBasicType()))
    {
        if (getShaderType() != GL_FRAGMENT_SHADER)
        {
            error(identifierLocation,
                  "undefined use of pixel local storage outside a fragment shader",
                  getBasicString(publicType.getBasicType()));
            return;
        }
        switch (layoutQualifier.imageInternalFormat)
        {
            case EiifR32F:
            case EiifRGBA8:
                if (publicType.getBasicType() != EbtPixelLocalANGLE)
                {
                    error(identifierLocation, "pixel local storage format requires pixelLocalANGLE",
                          getImageInternalFormatString(layoutQualifier.imageInternalFormat));
                }
                break;
            case EiifR32I:
            case EiifRGBA8I:
                if (publicType.getBasicType() != EbtIPixelLocalANGLE)
                {
                    error(identifierLocation,
                          "pixel local storage format requires ipixelLocalANGLE",
                          getImageInternalFormatString(layoutQualifier.imageInternalFormat));
                }
                break;
            case EiifR32UI:
            case EiifRGBA8UI:
                if (publicType.getBasicType() != EbtUPixelLocalANGLE)
                {
                    error(identifierLocation,
                          "pixel local storage format requires upixelLocalANGLE",
                          getImageInternalFormatString(layoutQualifier.imageInternalFormat));
                }
                break;
            case EiifRGBA8_SNORM:
            case EiifRGBA16F:
            case EiifRGBA32F:
            case EiifRGBA16I:
            case EiifRGBA32I:
            case EiifRGBA16UI:
            case EiifRGBA32UI:
            default:
                ASSERT(!IsValidWithPixelLocalStorage(layoutQualifier.imageInternalFormat));
                error(identifierLocation, "illegal pixel local storage format",
                      getImageInternalFormatString(layoutQualifier.imageInternalFormat));
                break;
            case EiifUnspecified:
                error(identifierLocation, "pixel local storage requires a format specifier",
                      "layout qualifier");
                break;
        }
        checkMemoryQualifierIsNotSpecified(publicType.memoryQualifier, identifierLocation);
        checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
    }
    else
    {
        checkInternalFormatIsNotSpecified(identifierLocation, layoutQualifier.imageInternalFormat);
        checkMemoryQualifierIsNotSpecified(publicType.memoryQualifier, identifierLocation);
    }

    if (IsAtomicCounter(publicType.getBasicType()))
    {
        atomicCounterQualifierErrorCheck(publicType, identifierLocation);
    }
    else
    {
        checkOffsetIsNotSpecified(identifierLocation, layoutQualifier.offset);
    }
}

void TParseContext::checkBindingIsValid(const TSourceLoc &identifierLocation, const TType &type)
{
    TLayoutQualifier layoutQualifier = type.getLayoutQualifier();
    // Note that the ESSL 3.10 section 4.4.5 is not particularly clear on how the binding qualifier
    // on arrays of arrays should be handled. We interpret the spec so that the binding value is
    // incremented for each element of the innermost nested arrays. This is in line with how arrays
    // of arrays of blocks are specified to behave in GLSL 4.50 and a conservative interpretation
    // when it comes to which shaders are accepted by the compiler.
    int arrayTotalElementCount = type.getArraySizeProduct();
    if (IsPixelLocal(type.getBasicType()))
    {
        checkPixelLocalStorageBindingIsValid(identifierLocation, type);
    }
    else if (mShaderVersion < 310)
    {
        checkBindingIsNotSpecified(identifierLocation, layoutQualifier.binding);
    }
    else if (IsImage(type.getBasicType()))
    {
        checkImageBindingIsValid(identifierLocation, layoutQualifier.binding,
                                 arrayTotalElementCount);
    }
    else if (IsSampler(type.getBasicType()))
    {
        checkSamplerBindingIsValid(identifierLocation, layoutQualifier.binding,
                                   arrayTotalElementCount);
    }
    else if (IsAtomicCounter(type.getBasicType()))
    {
        checkAtomicCounterBindingIsValid(identifierLocation, layoutQualifier.binding);
    }
    else
    {
        ASSERT(!IsOpaqueType(type.getBasicType()));
        checkBindingIsNotSpecified(identifierLocation, layoutQualifier.binding);
    }
}

void TParseContext::checkCanUseLayoutQualifier(const TSourceLoc &location)
{
    constexpr std::array<TExtension, 4u> extensions{
        {TExtension::EXT_shader_framebuffer_fetch,
         TExtension::EXT_shader_framebuffer_fetch_non_coherent,
         TExtension::KHR_blend_equation_advanced, TExtension::ANGLE_shader_pixel_local_storage}};
    if (getShaderVersion() < 300 && !checkCanUseOneOfExtensions(location, extensions))
    {
        error(location, "qualifier supported in GLSL ES 3.00 and above only", "layout");
    }
}

bool TParseContext::checkLayoutQualifierSupported(const TSourceLoc &location,
                                                  const ImmutableString &layoutQualifierName,
                                                  int versionRequired)
{

    if (mShaderVersion < versionRequired)
    {
        error(location, "invalid layout qualifier: not supported", layoutQualifierName);
        return false;
    }
    return true;
}

bool TParseContext::checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
                                                     const TLayoutQualifier &layoutQualifier)
{
    const sh::WorkGroupSize &localSize = layoutQualifier.localSize;
    for (size_t i = 0u; i < localSize.size(); ++i)
    {
        if (localSize[i] != -1)
        {
            error(location,
                  "invalid layout qualifier: only valid when used with 'in' in a compute shader "
                  "global layout declaration",
                  getWorkGroupSizeString(i));
            return false;
        }
    }

    return true;
}

void TParseContext::checkInternalFormatIsNotSpecified(const TSourceLoc &location,
                                                      TLayoutImageInternalFormat internalFormat)
{
    if (internalFormat != EiifUnspecified)
    {
        if (mShaderVersion < 310)
        {
            if (IsValidWithPixelLocalStorage(internalFormat))
            {
                error(location,
                      "invalid layout qualifier: not supported before GLSL ES 3.10, except pixel "
                      "local storage",
                      getImageInternalFormatString(internalFormat));
            }
            else
            {
                error(location, "invalid layout qualifier: not supported before GLSL ES 3.10",
                      getImageInternalFormatString(internalFormat));
            }
        }
        else
        {
            if (IsValidWithPixelLocalStorage(internalFormat))
            {
                error(location,
                      "invalid layout qualifier: only valid when used with images or pixel local "
                      "storage ",
                      getImageInternalFormatString(internalFormat));
            }
            else
            {
                error(location, "invalid layout qualifier: only valid when used with images",
                      getImageInternalFormatString(internalFormat));
            }
        }
    }
}

void TParseContext::checkIndexIsNotSpecified(const TSourceLoc &location, int index)
{
    if (index != -1)
    {
        error(location,
              "invalid layout qualifier: only valid when used with a fragment shader output in "
              "ESSL version >= 3.00 and EXT_blend_func_extended is enabled",
              "index");
    }
}

void TParseContext::checkBindingIsNotSpecified(const TSourceLoc &location, int binding)
{
    if (binding != -1)
    {
        if (mShaderVersion < 310)
        {
            error(location,
                  "invalid layout qualifier: only valid when used with pixel local storage",
                  "binding");
        }
        else
        {
            error(location,
                  "invalid layout qualifier: only valid when used with opaque types or blocks",
                  "binding");
        }
    }
}

void TParseContext::checkOffsetIsNotSpecified(const TSourceLoc &location, int offset)
{
    if (offset != -1)
    {
        error(location, "invalid layout qualifier: only valid when used with atomic counters",
              "offset");
    }
}

void TParseContext::checkImageBindingIsValid(const TSourceLoc &location,
                                             int binding,
                                             int arrayTotalElementCount)
{
    // Expects arraySize to be 1 when setting binding for only a single variable.
    if (binding >= 0 && binding + arrayTotalElementCount > mResources.MaxImageUnits)
    {
        error(location, "image binding greater than gl_MaxImageUnits", "binding");
    }
}

void TParseContext::checkSamplerBindingIsValid(const TSourceLoc &location,
                                               int binding,
                                               int arrayTotalElementCount)
{
    // Expects arraySize to be 1 when setting binding for only a single variable.
    if (binding >= 0 && binding + arrayTotalElementCount > mResources.MaxCombinedTextureImageUnits)
    {
        error(location, "sampler binding greater than maximum texture units", "binding");
    }
}

void TParseContext::checkBlockBindingIsValid(const TSourceLoc &location,
                                             const TQualifier &qualifier,
                                             int binding,
                                             int arraySize)
{
    int size = (arraySize == 0 ? 1 : arraySize);
    if (qualifier == EvqUniform)
    {
        if (binding + size > mResources.MaxUniformBufferBindings)
        {
            error(location, "uniform block binding greater than MAX_UNIFORM_BUFFER_BINDINGS",
                  "binding");
        }
    }
    else if (qualifier == EvqBuffer)
    {
        if (binding + size > mResources.MaxShaderStorageBufferBindings)
        {
            error(location,
                  "shader storage block binding greater than MAX_SHADER_STORAGE_BUFFER_BINDINGS",
                  "binding");
        }
    }
}
void TParseContext::checkAtomicCounterBindingIsValid(const TSourceLoc &location, int binding)
{
    if (binding >= mResources.MaxAtomicCounterBindings)
    {
        error(location, "atomic counter binding greater than gl_MaxAtomicCounterBindings",
              "binding");
    }
}

void TParseContext::checkPixelLocalStorageBindingIsValid(const TSourceLoc &location,
                                                         const TType &type)
{
    TLayoutQualifier layoutQualifier = type.getLayoutQualifier();
    if (type.isArray())
    {
        // PLS is not allowed in arrays.
        // TODO(anglebug.com/40096838): Consider allowing this once more backends are implemented.
        error(location, "pixel local storage handles cannot be aggregated in arrays", "array");
    }
    else if (layoutQualifier.binding < 0)
    {
        error(location, "pixel local storage requires a binding index", "layout qualifier");
    }
    // TODO(anglebug.com/40096838):
    else if (layoutQualifier.binding >= mResources.MaxPixelLocalStoragePlanes)
    {
        error(location, "pixel local storage binding out of range", "layout qualifier");
    }
    else if (mPLSLayouts.find(layoutQualifier.binding) != mPLSLayouts.end())
    {
        error(location, "duplicate pixel local storage binding index",
              std::to_string(layoutQualifier.binding).c_str());
    }
    else
    {
        mPLSLayouts[layoutQualifier.binding] = {
            .format      = ImageFormatToPLSFormat(layoutQualifier.imageInternalFormat),
            .noncoherent = layoutQualifier.noncoherent,
        };
        // "mPLSLayouts" is how we know whether any pixel local storage uniforms have been declared,
        // so flush the queue of potential errors once mPLSLayouts isn't empty.
        if (!mPLSPotentialErrors.empty())
        {
            for (const auto &[loc, op] : mPLSPotentialErrors)
            {
                errorIfPLSDeclared(loc, op);
            }
            mPLSPotentialErrors.clear();
        }
    }
}

void TParseContext::checkUniformLocationInRange(const TSourceLoc &location,
                                                int objectLocationCount,
                                                const TLayoutQualifier &layoutQualifier)
{
    int loc = layoutQualifier.location;
    if (loc >= 0)  // Shader-specified location
    {
        if (loc >= mResources.MaxUniformLocations ||
            objectLocationCount > mResources.MaxUniformLocations ||
            static_cast<unsigned int>(loc) + static_cast<unsigned int>(objectLocationCount) >
                static_cast<unsigned int>(mResources.MaxUniformLocations))
        {
            error(location, "Uniform location out of range", "location");
        }
    }
}

void TParseContext::checkAttributeLocationInRange(const TSourceLoc &location,
                                                  int objectLocationCount,
                                                  const TLayoutQualifier &layoutQualifier)
{
    int loc = layoutQualifier.location;
    if (loc >= 0)  // Shader-specified location
    {
        if (loc >= mResources.MaxVertexAttribs ||
            objectLocationCount > mResources.MaxVertexAttribs ||
            static_cast<unsigned int>(loc) + static_cast<unsigned int>(objectLocationCount) >
                static_cast<unsigned int>(mResources.MaxVertexAttribs))
        {
            error(location, "Attribute location out of range", "location");
        }
    }
}

void TParseContext::checkDepthIsNotSpecified(const TSourceLoc &location, TLayoutDepth depth)
{
    if (depth != EdUnspecified)
    {
        error(location, "invalid layout qualifier: only valid on gl_FragDepth",
              getDepthString(depth));
    }
}

void TParseContext::checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv)
{
    if (yuv != false)
    {
        error(location, "invalid layout qualifier: only valid on program outputs", "yuv");
    }
}

void TParseContext::checkEarlyFragmentTestsIsNotSpecified(const TSourceLoc &location,
                                                          bool earlyFragmentTests)
{
    if (earlyFragmentTests != false)
    {
        error(location,
              "invalid layout qualifier: only valid when used with 'in' in a fragment shader",
              "early_fragment_tests");
    }
}

void TParseContext::checkNoncoherentIsSpecified(const TSourceLoc &location, bool noncoherent)
{
    if (noncoherent == false)
    {
        error(location,
              "'noncoherent' qualifier must be used when "
              "GL_EXT_shader_framebuffer_fetch_non_coherent extension is used",
              "noncoherent");
    }
}

void TParseContext::checkNoncoherentIsNotSpecified(const TSourceLoc &location, bool noncoherent)
{
    if (noncoherent != false)
    {
        error(location,
              "invalid layout qualifier: only valid when used with 'gl_LastFragData', the "
              "variable decorated with 'inout' in a fragment shader, or pixel local storage",
              "noncoherent");
    }
}

void TParseContext::checkTCSOutVarIndexIsValid(TIntermBinary *binaryExpression,
                                               const TSourceLoc &location)
{
    ASSERT(binaryExpression->getOp() == EOpIndexIndirect ||
           binaryExpression->getOp() == EOpIndexDirect);
    const TIntermSymbol *intermSymbol = binaryExpression->getRight()->getAsSymbolNode();
    if ((intermSymbol == nullptr) || (intermSymbol->getName() != "gl_InvocationID"))
    {
        error(location,
              "tessellation-control per-vertex output l-value must be indexed with "
              "gl_InvocationID",
              "[");
    }
}

void TParseContext::functionCallRValueLValueErrorCheck(const TFunction *fnCandidate,
                                                       TIntermAggregate *fnCall)
{
    for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
    {
        TQualifier qual        = fnCandidate->getParam(i)->getType().getQualifier();
        TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped();
        bool argumentIsRead    = (IsQualifierUnspecified(qual) || qual == EvqParamIn ||
                               qual == EvqParamInOut || qual == EvqParamConst);
        if (argumentIsRead)
        {
            markStaticUseIfSymbol(argument);
            if (!IsImage(argument->getBasicType()))
            {
                if (argument->getMemoryQualifier().writeonly)
                {
                    error(argument->getLine(),
                          "Writeonly value cannot be passed for 'in' or 'inout' parameters.",
                          fnCall->functionName());
                    return;
                }
            }
        }
        if (qual == EvqParamOut || qual == EvqParamInOut)
        {
            if (!checkCanBeLValue(argument->getLine(), "assign", argument))
            {
                error(argument->getLine(),
                      "Constant value cannot be passed for 'out' or 'inout' parameters.",
                      fnCall->functionName());
                return;
            }
        }
    }
}

void TParseContext::checkInvariantVariableQualifier(bool invariant,
                                                    const TQualifier qualifier,
                                                    const TSourceLoc &invariantLocation)
{
    if (!invariant)
    {
        return;
    }

    if (mShaderVersion < 300)
    {
        // input variables in the fragment shader can be also qualified as invariant
        if (!sh::CanBeInvariantESSL1(qualifier))
        {
            error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
        }
    }
    else
    {
        if (!sh::CanBeInvariantESSL3OrGreater(qualifier))
        {
            error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
        }
    }
}

void TParseContext::checkAdvancedBlendEquationsNotSpecified(
    const TSourceLoc &location,
    const AdvancedBlendEquations &advancedBlendEquations,
    const TQualifier &qualifier)
{
    if (advancedBlendEquations.any() && qualifier != EvqFragmentOut)
    {
        error(location,
              "invalid layout qualifier: blending equation qualifiers are only permitted on the "
              "fragment 'out' qualifier ",
              "blend_support_qualifier");
    }
}

bool TParseContext::isExtensionEnabled(TExtension extension) const
{
    return IsExtensionEnabled(extensionBehavior(), extension);
}

void TParseContext::handleExtensionDirective(const TSourceLoc &loc,
                                             const char *extName,
                                             const char *behavior)
{
    angle::pp::SourceLocation srcLoc;
    srcLoc.file = loc.first_file;
    srcLoc.line = loc.first_line;
    mDirectiveHandler.handleExtension(srcLoc, extName, behavior);
}

void TParseContext::handlePragmaDirective(const TSourceLoc &loc,
                                          const char *name,
                                          const char *value,
                                          bool stdgl)
{
    angle::pp::SourceLocation srcLoc;
    srcLoc.file = loc.first_file;
    srcLoc.line = loc.first_line;
    mDirectiveHandler.handlePragma(srcLoc, name, value, stdgl);
}

sh::WorkGroupSize TParseContext::getComputeShaderLocalSize() const
{
    sh::WorkGroupSize result(-1);
    for (size_t i = 0u; i < result.size(); ++i)
    {
        if (mComputeShaderLocalSizeDeclared && mComputeShaderLocalSize[i] == -1)
        {
            result[i] = 1;
        }
        else
        {
            result[i] = mComputeShaderLocalSize[i];
        }
    }
    return result;
}

TIntermConstantUnion *TParseContext::addScalarLiteral(const TConstantUnion *constantUnion,
                                                      const TSourceLoc &line)
{
    TIntermConstantUnion *node = new TIntermConstantUnion(
        constantUnion, TType(constantUnion->getType(), EbpUndefined, EvqConst));
    node->setLine(line);
    pushConstant(constantUnion, node->getType());
    return node;
}

/////////////////////////////////////////////////////////////////////////////////
//
// Non-Errors.
//
/////////////////////////////////////////////////////////////////////////////////

const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
                                                 const ImmutableString &name,
                                                 const TSymbol *symbol)
{
    if (!symbol)
    {
        error(location, "undeclared identifier", name);
        return nullptr;
    }

    if (!symbol->isVariable())
    {
        error(location, "variable expected", name);
        return nullptr;
    }

    const TVariable *variable = static_cast<const TVariable *>(symbol);

    if (!variable->extensions().empty() && variable->extensions()[0] != TExtension::UNDEFINED)
    {
        checkCanUseOneOfExtensions(location, variable->extensions());
    }

    // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables
    if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared &&
        variable->getType().getQualifier() == EvqWorkGroupSize)
    {
        error(location,
              "It is an error to use gl_WorkGroupSize before declaring the local group size",
              "gl_WorkGroupSize");
    }

    // If EXT_shader_framebuffer_fetch_non_coherent is used, gl_LastFragData should be decorated
    // with 'layout(noncoherent)' EXT_shader_framebuffer_fetch_non_coherent spec: "Unless the
    // GL_EXT_shader_framebuffer_fetch extension  has been enabled in addition, it's an error to use
    // gl_LastFragData if it hasn't been explicitly redeclared with layout(noncoherent)."
    if (isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch_non_coherent) &&
        !isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch) &&
        variable->getType().getQualifier() == EvqLastFragData)
    {
        checkNoncoherentIsSpecified(location, variable->getType().getLayoutQualifier().noncoherent);
    }

    // When EXT_separate_shader_objects is enabled, gl_Position and gl_PointSize must both be
    // redeclared before either is accessed:
    //
    // > The following vertex shader outputs may be redeclared at global scope to
    // > specify a built-in output interface, with or without special qualifiers:
    // >
    // >     gl_Position
    // >     gl_PointSize
    // >
    // >   When compiling shaders using either of the above variables, both such
    // >   variables must be redeclared prior to use.  ((Note:  This restriction
    // >   applies only to shaders using version 300 that enable the
    // >   EXT_separate_shader_objects extension; shaders not enabling the
    // >   extension do not have this requirement.))
    //
    // However, there are dEQP tests that enable all extensions and don't actually redeclare these
    // variables.  Per https://gitlab.khronos.org/opengl/API/-/issues/169, there are drivers that do
    // enforce this, but they fail linking instead of compilation.
    //
    // In ANGLE, we make sure that they are both redeclared before use if any is redeclared, but if
    // neither are redeclared, we don't fail compilation.  Currently, linking also doesn't fail in
    // ANGLE (similarly to almost all other drivers).
    if (isExtensionEnabled(TExtension::EXT_separate_shader_objects) &&
        mShaderType == GL_VERTEX_SHADER)
    {
        if (variable->getType().getQualifier() == EvqPosition ||
            variable->getType().getQualifier() == EvqPointSize)
        {
            mPositionOrPointSizeUsedForSeparateShaderObject = true;
            const bool eitherIsRedeclared = mPositionRedeclaredForSeparateShaderObject ||
                                            mPointSizeRedeclaredForSeparateShaderObject;
            const bool bothAreRedeclared = mPositionRedeclaredForSeparateShaderObject &&
                                           mPointSizeRedeclaredForSeparateShaderObject;

            if (eitherIsRedeclared && !bothAreRedeclared)
            {
                error(location,
                      "When EXT_separate_shader_objects is enabled, both gl_Position and "
                      "gl_PointSize must be redeclared before either is used",
                      name);
            }
        }
    }

    return variable;
}

ir::VariableId TParseContext::declareBuiltInOnFirstUse(const TVariable *variable)
{
    if (variable->symbolType() == SymbolType::BuiltIn &&
        mVariableToId.find(variable) == mVariableToId.end())
    {
        const TType *variableType = &variable->getType();

        // For and clip/cull distance, let the IR know that they are not actually sized yet.
        if (variableType->getQualifier() == EvqClipDistance ||
            variableType->getQualifier() == EvqCullDistance)
        {
            TType *unsizedArrayType = new TType(*variableType);
            unsizedArrayType->toArrayBaseType();
            unsizedArrayType->makeArray(0);
            variableType = unsizedArrayType;
        }

        // For gl_FragData, change the array size to 1 if MRT is not supported; only index 0 is
        // valid for access.  Note that gl_FragData usage itself is restricted to ESSL 100, so a
        // version check is unnecessary.
        if (variableType->getQualifier() == EvqFragData &&
            !isExtensionEnabled(TExtension::EXT_draw_buffers))
        {
            TType *singleElementArrayType = new TType(*variableType);
            singleElementArrayType->toArrayBaseType();
            singleElementArrayType->makeArray(1);
            variableType = singleElementArrayType;
        }

        const ir::TypeId typeId = getTypeId(*variableType);
        const ir::VariableId id = mIRBuilder.declareInterfaceVariable(
            variable->name(), typeId, *variableType, ir::DeclarationSource::Internal);
        mVariableToId[variable] = VariableToIdInfo{id, VariableToIdInfo::kNoImplicitField};

        switch (variableType->getQualifier())
        {
            case EvqClipDistance:
                mClipDistanceInfo.id = id;
                break;
            case EvqCullDistance:
                mCullDistanceInfo.id = id;
                break;
            default:
                break;
        }

        return id;
    }

    if (mDiagnostics->numErrors() > 0)
    {
        return {};
    }

    return mVariableToId.at(variable).id;
}

void TParseContext::declareFunction(const TFunction *function, FunctionDeclaration declaration)
{
    // If the function prototype hasn't been previously encountered, this is a new function that
    // should be declared to the IR first.
    if (mFunctionToId.find(function) == mFunctionToId.end())
    {
        TVector<ir::VariableId> params;
        TVector<TQualifier> paramDirections;
        for (size_t i = 0; i < function->getParamCount(); ++i)
        {
            const TVariable *param = function->getParam(i);
            const TType &paramType = param->getType();

            ir::VariableId paramId = mIRBuilder.declareFunctionParam(
                param->name(), getTypeId(paramType), paramType, paramType.getQualifier());
            mVariableToId[param] = VariableToIdInfo{paramId, VariableToIdInfo::kNoImplicitField};

            params.push_back(paramId);
            paramDirections.push_back(paramType.getQualifier());
        }

        mFunctionToId[function] = ANGLE_UNSAFE_TODO(mIRBuilder.newFunction(
            function->name(), angle::Span(params.data(), params.size()),
            angle::Span(paramDirections.data(), paramDirections.size()),
            getTypeId(function->getReturnType()), function->getReturnType()));
    }
    else if (declaration == FunctionDeclaration::Definition)
    {
        TVector<ImmutableString> paramNames;
        TVector<ir::VariableId> paramIds(function->getParamCount());
        for (size_t i = 0; i < function->getParamCount(); ++i)
        {
            const TVariable *param = function->getParam(i);
            paramNames.push_back(param->name());
        }
        ANGLE_UNSAFE_TODO(mIRBuilder.updateFunctionParamNames(
            mFunctionToId[function], angle::Span(paramNames.data(), paramNames.size()),
            angle::Span(paramIds.data(), paramIds.size())));

        // When a prototype is previously visited, `declareFunction` has already created the
        // variables for the function parameters in the |if| above.  When the function prototype is
        // visited again during function definition, the real argument names are provided (so the
        // variables should be renamed).  New |TVariable|s are also created by the parser, which
        // should map to the same IR ids.  At this point, the old |TVariable|s are lost, so the IR
        // returns the variable ids for the parameters.
        for (size_t i = 0; i < function->getParamCount(); ++i)
        {
            const TVariable *param = function->getParam(i);
            mVariableToId[param] =
                VariableToIdInfo{paramIds[i], VariableToIdInfo::kNoImplicitField};
        }
    }
}

TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location,
                                                     const ImmutableString &name,
                                                     const TSymbol *symbol)
{
    const TVariable *variable = getNamedVariable(location, name, symbol);

    if (!variable)
    {
        TIntermTyped *node = CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
        node->setLine(location);
        return node;
    }

    const TType &variableType = variable->getType();
    TIntermTyped *node        = nullptr;

    if (variable->getConstPointer() && variableType.canReplaceWithConstantUnion())
    {
        const TConstantUnion *constArray = variable->getConstPointer();
        node                             = new TIntermConstantUnion(constArray, variableType);
    }
    else if (variableType.getQualifier() == EvqWorkGroupSize && mComputeShaderLocalSizeDeclared)
    {
        // gl_WorkGroupSize can be used to size arrays according to the ESSL 3.10.4 spec, so it
        // needs to be added to the AST as a constant and not as a symbol.
        sh::WorkGroupSize workGroupSize = getComputeShaderLocalSize();
        TConstantUnion *constArray      = new TConstantUnion[3];
        for (size_t i = 0; i < 3; ++i)
        {
            ANGLE_UNSAFE_TODO(constArray[i]).setUConst(static_cast<unsigned int>(workGroupSize[i]));
        }

        ASSERT(variableType.getBasicType() == EbtUInt);
        ASSERT(variableType.getObjectSize() == 3);

        TType type(variableType);
        type.setQualifier(EvqConst);
        node = new TIntermConstantUnion(constArray, type);
    }
    else if ((mGeometryShaderInputPrimitiveType != EptUndefined) &&
             (variableType.getQualifier() == EvqPerVertexIn))
    {
        ASSERT(symbolTable.getGlInVariableWithArraySize() != nullptr);
        variable = symbolTable.getGlInVariableWithArraySize();
        node     = new TIntermSymbol(variable);
    }
    else
    {
        // gl_LastFragDepthARM and gl_LastFragStencilARM cannot be accessed if early_fragment_tests
        // is specified.
        if ((variableType.getQualifier() == EvqLastFragDepth ||
             variableType.getQualifier() == EvqLastFragStencil) &&
            isEarlyFragmentTestsSpecified())
        {
            error(location,
                  "gl_LastFragDepthARM and gl_LastFragStencilARM cannot be accessed because "
                  "early_fragment_tests is specified",
                  name);
        }

        node = new TIntermSymbol(variable);
    }
    ASSERT(node != nullptr);
    node->setLine(location);

    // Push the variable or its equivalent constant.  Note that when the variable is declared as
    // `const`, the variable is pushed instead of the constant so its precision is retained.
    if (variableType.getQualifier() == EvqConst &&
        mVariableToId.find(variable) != mVariableToId.end())
    {
        pushVariable(variable);
    }
    else if (node->getAsConstantUnion())
    {
        pushConstant(node->getAsConstantUnion()->getConstantValue(), variableType);
    }
    else if (variable->getConstPointer())
    {
        pushConstant(variable->getConstPointer(), variableType);
    }
    else if (node->getAsSymbolNode())
    {
        // For built-ins, declare them in the IR on first reference.
        declareBuiltInOnFirstUse(variable);
        pushVariable(variable);

        if (variableType.getQualifier() == EvqFragDepth)
        {
            mFragmentOutputFragDepthUsed = true;
        }
    }

    return node;
}

void TParseContext::adjustRedeclaredBuiltInType(const TSourceLoc &line,
                                                const ImmutableString &identifier,
                                                TType *type)
{
    if (identifier == "gl_ClipDistance")
    {
        const TQualifier qualifier = type->getQualifier();
        if ((mShaderType == GL_VERTEX_SHADER &&
             !(qualifier == EvqVertexOut || qualifier == EvqVaryingOut)) ||
            (mShaderType == GL_FRAGMENT_SHADER && qualifier != EvqFragmentIn))
        {
            error(line, "invalid or missing storage qualifier", identifier);
            return;
        }

        type->setQualifier(EvqClipDistance);
    }
    else if (identifier == "gl_CullDistance")
    {
        const TQualifier qualifier = type->getQualifier();
        if ((mShaderType == GL_VERTEX_SHADER && qualifier != EvqVertexOut) ||
            (mShaderType == GL_FRAGMENT_SHADER && qualifier != EvqFragmentIn))
        {
            error(line, "invalid or missing storage qualifier", identifier);
            return;
        }

        type->setQualifier(EvqCullDistance);
    }
    else if (identifier == "gl_LastFragData")
    {
        type->setQualifier(EvqLastFragData);
    }
    else if (identifier == "gl_LastFragColorARM")
    {
        type->setQualifier(EvqLastFragColor);
    }
    else if (identifier == "gl_LastFragDepthARM")
    {
        type->setQualifier(EvqLastFragDepth);
    }
    else if (identifier == "gl_LastFragStencilARM")
    {
        type->setQualifier(EvqLastFragStencil);
    }
    else if (identifier == "gl_Position")
    {
        type->setQualifier(EvqPosition);
    }
    else if (identifier == "gl_PointSize")
    {
        type->setQualifier(EvqPointSize);
    }
}

// Initializers show up in several places in the grammar.  Have one set of
// code to handle them here.
//
// Returns true on success.
bool TParseContext::executeInitializer(const TSourceLoc &line,
                                       const ImmutableString &identifier,
                                       TType *type,
                                       TIntermTyped *initializer,
                                       TIntermBinary **initNode)
{
    ASSERT(initNode != nullptr);
    ASSERT(*initNode == nullptr);

    if (type->isUnsizedArray())
    {
        // In case initializer is not an array or type has more dimensions than initializer, this
        // will default to setting array sizes to 1. We have not checked yet whether the initializer
        // actually is an array or not. Having a non-array initializer for an unsized array will
        // result in an error later, so we don't generate an error message here.
        type->sizeUnsizedArrays(initializer->getType().getArraySizes());
    }

    type->setTypeId(getTypeId(*type));

    const TQualifier qualifier = type->getQualifier();

    bool constError = false;
    if (qualifier == EvqConst)
    {
        if (EvqConst != initializer->getType().getQualifier())
        {
            TInfoSinkBase reasonStream;
            reasonStream << "assigning non-constant to '" << *type << "'";
            error(line, reasonStream.c_str(), "=");

            // We're still going to declare the variable to avoid extra error messages.
            type->setQualifier(EvqTemporary);
            constError = true;
        }
    }

    TVariable *variable = nullptr;
    if (!declareVariable(line, identifier, type, GeomTessArray::Sized, &variable))
    {
        return false;
    }

    if (constError)
    {
        return false;
    }

    bool nonConstGlobalInitializers =
        IsExtensionEnabled(mDirectiveHandler.extensionBehavior(),
                           TExtension::EXT_shader_non_constant_global_initializers);
    bool globalInitWarning = false;
    bool tooComplex        = false;
    if (symbolTable.atGlobalLevel())
    {
        bool valid = ValidateGlobalInitializer(
            initializer, mShaderVersion, sh::IsWebGLBasedSpec(mShaderSpec),
            nonConstGlobalInitializers, &globalInitWarning, &tooComplex);
        if (!valid || tooComplex)
        {
            // Error message does not completely match behavior with ESSL 1.00, but
            // we want to steer developers towards only using constant expressions.
            //
            // Note: the "Expression too complex" check can be removed once IR is the only path, as
            // it's not sensitive to expression depth.
            error(line,
                  tooComplex ? "Expression too complex"
                             : "global variable initializers must be constant expressions",
                  "=");
            return false;
        }
        if (globalInitWarning)
        {
            warning(line,
                    "global variable initializers should be constant expressions "
                    "(uniforms and globals are allowed in global initializers for legacy "
                    "compatibility)",
                    "=");
        }
    }

    // identifier must be of type constant, a global, or a temporary
    if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst))
    {
        error(line, " cannot initialize this type of qualifier ",
              variable->getType().getQualifierString());
        return false;
    }

    TIntermSymbol *intermSymbol = new TIntermSymbol(variable);
    intermSymbol->setLine(line);

    if (!binaryOpCommonCheck(EOpInitialize, intermSymbol, initializer, line))
    {
        assignError(line, "=", variable->getType(), initializer->getType());
        return false;
    }

    const TConstantUnion *initializerConstArray = initializer->getConstantValue();
    if (initializerConstArray)
    {
        if (mCompileOptions.rejectWebglShadersWithUndefinedBehavior)
        {
            // If this is `bool variable = true`, track it.  If it's ever used as l-value, it's
            // removed from this list.  At the end of parse, if a variable is in this list, it's set
            // to true and never modified.
            if (type->isScalarBool() && initializerConstArray->getBConst())
            {
                mConstantTrueVariables.insert(variable->uniqueId());
            }
        }

        // Save the constant folded value to the variable if possible.
        if (qualifier == EvqConst)
        {
            variable->shareConstPointer(initializerConstArray);
            if (initializer->getType().canReplaceWithConstantUnion())
            {
                mIRBuilder.initialize(mVariableToId.at(variable).id);
                ASSERT(*initNode == nullptr);
                return true;
            }
        }
    }

    mIRBuilder.initialize(mVariableToId.at(variable).id);

    *initNode = new TIntermBinary(EOpInitialize, intermSymbol, initializer);
    markStaticUseIfSymbol(initializer);
    (*initNode)->setLine(line);
    return true;
}

TIntermNode *TParseContext::addConditionInitializer(const TPublicType &pType,
                                                    const ImmutableString &identifier,
                                                    TIntermTyped *initializer,
                                                    const TSourceLoc &loc)
{
    checkIsScalarBool(loc, pType);
    TIntermBinary *initNode = nullptr;
    TType *type             = new TType(pType);
    if (executeInitializer(loc, identifier, type, initializer, &initNode))
    {
        // The initializer is valid. The init condition needs to have a node - either the
        // initializer node, or a constant node in case the initialized variable is const and won't
        // be recorded in the AST.
        if (initNode == nullptr)
        {
            return initializer;
        }
        else
        {
            TIntermDeclaration *declaration = new TIntermDeclaration();
            declaration->appendDeclarator(initNode);
            return declaration;
        }
    }
    return nullptr;
}

void TParseContext::checkESSL100ForLoopInit(TIntermNode *init, const TSourceLoc &line)
{
    // The loop must be a `for` loop, and have the following form according to ESSL 100 spec,
    // Appendix A:
    //
    //    for (type symbol = initializer; symbol op constant; symbol += constant)
    //
    // Validate the init statement here.
    if (init == nullptr)
    {
        error(line, "Missing init declaration", "for");
        return;
    }

    //
    // init-declaration has the form:
    //     type-specifier identifier = constant-expression
    //
    TIntermDeclaration *decl = init->getAsDeclarationNode();
    if (decl == nullptr)
    {
        error(line, "Invalid init declaration", "for");
        return;
    }
    TIntermSequence *declSeq = decl->getSequence();
    if (declSeq->size() != 1)
    {
        error(line, "Invalid init declaration", "for");
        return;
    }
    TIntermBinary *declInit = (*declSeq)[0]->getAsBinaryNode();
    if (declInit == nullptr || declInit->getOp() != EOpInitialize)
    {
        error(line, "Invalid init declaration", "for");
        return;
    }
    TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode();
    if (symbol == nullptr)
    {
        error(line, "Invalid init declaration", "for");
        return;
    }
    // The loop index has type int or float.
    TBasicType type = symbol->getBasicType();
    if ((type != EbtInt && type != EbtUInt && type != EbtFloat) || !symbol->isScalar())
    {
        error(line, "Invalid type for loop index", getBasicString(type));
        return;
    }
    // The loop index is initialized with constant expression.
    if (!IsESSL100ConstantExpression(declInit->getRight()))
    {
        error(line, "Loop index cannot be initialized with non-constant expression",
              symbol->getName());
        return;
    }

    // Keep track of the loop symbol.  The loop symbol is not allowed to be modified in the body.
    ASSERT(mControlFlow.back().type == ControlFlowType::Loop);
    mControlFlow.back().forLoopSymbol = symbol->uniqueId();
}

void TParseContext::checkESSL100ForLoopCondition(TIntermNode *condition, const TSourceLoc &line)
{
    if (condition == nullptr)
    {
        error(line, "Missing condition", "for");
        return;
    }

    // condition has the form:
    //     loop_index relational_operator constant_expression
    TIntermBinary *binOp = condition->getAsBinaryNode();
    if (binOp == nullptr)
    {
        error(line, "Invalid condition", "for");
        return;
    }
    // Loop index should be to the left of relational operator.
    TIntermSymbol *symbol = binOp->getLeft()->getAsSymbolNode();
    if (symbol == nullptr)
    {
        error(line, "Invalid condition", "for");
        return;
    }
    ASSERT(mControlFlow.back().type == ControlFlowType::Loop);
    if (symbol->uniqueId() != mControlFlow.back().forLoopSymbol)
    {
        error(line, "Expected loop index", symbol->getName());
        return;
    }
    // Relational operator is one of: > >= < <= == or !=.
    switch (binOp->getOp())
    {
        case EOpEqual:
        case EOpNotEqual:
        case EOpLessThan:
        case EOpGreaterThan:
        case EOpLessThanEqual:
        case EOpGreaterThanEqual:
            break;
        default:
            error(line, "Invalid relational operator", GetOperatorString(binOp->getOp()));
            return;
    }
    // Loop index must be compared with a constant.
    if (!IsESSL100ConstantExpression(binOp->getRight()))
    {
        error(line, "Loop index cannot be compared with non-constant expression",
              symbol->getName());
        return;
    }
}

void TParseContext::checkESSL100ForLoopContinue(TIntermNode *statement, const TSourceLoc &line)
{
    if (statement == nullptr)
    {
        error(line, "Missing expression", "for");
        return;
    }

    // for expression has one of the following forms:
    //
    //     loop_index++
    //     loop_index--
    //     loop_index += constant_expression
    //     loop_index -= constant_expression
    //     ++loop_index
    //     --loop_index
    //
    // The last two forms are not specified in the spec, but we're assuming its an oversight.
    TIntermUnary *unOp   = statement->getAsUnaryNode();
    TIntermBinary *binOp = unOp ? nullptr : statement->getAsBinaryNode();

    TOperator op            = EOpNull;
    const TFunction *opFunc = nullptr;
    TIntermSymbol *symbol   = nullptr;
    if (unOp != nullptr)
    {
        op     = unOp->getOp();
        opFunc = unOp->getFunction();
        symbol = unOp->getOperand()->getAsSymbolNode();
    }
    else if (binOp != nullptr)
    {
        op     = binOp->getOp();
        symbol = binOp->getLeft()->getAsSymbolNode();
    }

    // The operand must be loop index.
    if (symbol == nullptr)
    {
        error(line, "Invalid expression", "for");
        return;
    }
    ASSERT(mControlFlow.back().type == ControlFlowType::Loop);
    if (symbol->uniqueId() != mControlFlow.back().forLoopSymbol)
    {
        error(line, "Expected loop index", symbol->getName());
        return;
    }

    // The operator is one of: ++ -- += -=.
    switch (op)
    {
        case EOpPostIncrement:
        case EOpPostDecrement:
        case EOpPreIncrement:
        case EOpPreDecrement:
            ASSERT(unOp != nullptr && binOp == nullptr);
            break;
        case EOpAddAssign:
        case EOpSubAssign:
            ASSERT(unOp == nullptr && binOp != nullptr);
            break;
        default:
            if (BuiltInGroup::IsBuiltIn(op))
            {
                ASSERT(opFunc != nullptr);
                error(line, "Invalid built-in call", opFunc->name().data());
            }
            else
            {
                error(line, "Invalid operator", GetOperatorString(op));
            }
            return;
    }

    // Loop index must be incremented/decremented with a constant.
    if (binOp != nullptr)
    {
        if (!IsESSL100ConstantExpression(binOp->getRight()))
        {
            error(line, "Loop index cannot be modified by non-constant expression",
                  symbol->getName());
            return;
        }
    }

    // After the continue statement is visited, mark the for loop symbol as needing to stay
    // constant.
    mControlFlow.back().isForLoopSymbolConstant = true;
}

bool TParseContext::isESSL100ConstantLoopSymbol(TIntermSymbol *symbol)
{
    ASSERT(symbol != nullptr);
    const TSymbolUniqueId symbolUniqueId = symbol->uniqueId();

    for (const ControlFlow &controlFlow : mControlFlow)
    {
        if (controlFlow.isForLoopSymbolConstant && symbolUniqueId == controlFlow.forLoopSymbol)
        {
            return true;
        }
    }
    return false;
}

void TParseContext::checkESSL100NoLoopSymbolAssign(TIntermSymbol *symbol, const TSourceLoc &line)
{
    if (isESSL100ConstantLoopSymbol(symbol))
    {
        error(line, "Loop index cannot be statically assigned to within the body of the loop",
              symbol->getName());
    }
}

void TParseContext::checkESSL100ConstantIndex(TIntermTyped *index, const TSourceLoc &line)
{
    // According to ESSL 100 spec, Appendix A:
    //
    // > constant-index-expressions are a superset of constant-expressions.
    // > Constant-index-expressions can include loop indices as defined in GLSL ES 1.0 spec,
    // > Appendix A, section 4.
    //
    // > The following are constant-index-expressions:
    // > - Constant expressions
    // > - Loop indices as defined in section 4
    // > - Expressions composed of both of the above
    //
    // To implement the above, all subnodes of index are visited:
    //
    // * If any are symbols, they must be a loop index.
    // * Otherwise if they have no children, they must have a constant value.
    // * No user function calls are allowed (every other forbidden function call ends up using a
    //   symbol, such as texture2D())
    //
    // Since the expression complexity validation is not done yet (check against
    // MaxExpressionComplexity), this operation is not done with recursion.
    std::vector<TIntermTyped *> toInspect;
    toInspect.push_back(index);

    while (!toInspect.empty())
    {
        TIntermTyped *node = toInspect.back();
        toInspect.pop_back();

        if (node->getAsAggregate() && node->getAsAggregate()->isFunctionCall())
        {
            error(line, "Index expression cannot contain function calls", "[]");
            return;
        }

        size_t childCount = node->getChildCount();
        if (childCount == 0)
        {
            // If a symbol is used that's not const or a loop index, this expression is not allowed.
            TIntermSymbol *symbol = node->getAsSymbolNode();
            if (symbol != nullptr)
            {
                if (symbol->getQualifier() != EvqConst && !isESSL100ConstantLoopSymbol(symbol))
                {
                    error(line, "Index expression can only contain const or loop symbols",
                          symbol->getName().data());
                    return;
                }
            }
            else if (!node->hasConstantValue())
            {
                error(line, "Index expression must be constant", "[]");
                return;
            }
        }

        for (size_t childIndex = 0; childIndex < childCount; ++childIndex)
        {
            toInspect.push_back(node->getChildNode(childIndex)->getAsTyped());
        }
    }
}

void TParseContext::popControlFlow()
{
    ASSERT(!mControlFlow.empty());
    const ControlFlow justEndedControlFlow = mControlFlow.back();
    mControlFlow.pop_back();

    if (mCompileOptions.rejectWebglShadersWithUndefinedBehavior)
    {
        // Carry information about whether break or return are present in the block to the parent
        // block.
        if (!mControlFlow.empty())
        {
            mControlFlow.back().hasReturn =
                mControlFlow.back().hasReturn || justEndedControlFlow.hasReturn;
            // `break` in an if block or just a nested block also break out of the outer construct.
            if (justEndedControlFlow.type == ControlFlowType::If ||
                justEndedControlFlow.type == ControlFlowType::NewScope)
            {
                mControlFlow.back().hasBreak =
                    mControlFlow.back().hasBreak || justEndedControlFlow.hasBreak;
            }
        }

        if (justEndedControlFlow.type != ControlFlowType::Loop || justEndedControlFlow.hasReturn ||
            justEndedControlFlow.hasBreak)
        {
            return;
        }

        // If the loop has a constant-true condition without a break or return, it will loop
        // forever. Give a parse error about it.
        if (justEndedControlFlow.isLoopConditionConstantTrue)
        {
            error(justEndedControlFlow.loopLocation, "Infinite loop detected in the shader", "");
            return;
        }

        // Otherwise, if the loop is based on a symbol that stays constant-true until the end of the
        // shader, that's also an obvious infinite loop.
        if (justEndedControlFlow.loopConditionConstantTrueSymbol != nullptr &&
            mConstantTrueVariables.find(
                justEndedControlFlow.loopConditionConstantTrueSymbol->uniqueId()) !=
                mConstantTrueVariables.end())
        {
            // But we can't know whether the variable will stay unchanged until the end of the
            // shader, so the decision to produce a compile error is deferred.
            VariableAndLocation loopVariable;
            loopVariable.line     = justEndedControlFlow.loopLocation;
            loopVariable.variable = justEndedControlFlow.loopConditionConstantTrueSymbol;

            mPossiblyInfiniteLoops.push_back(loopVariable);
        }
    }
}

void TParseContext::beginNestedScope()
{
    symbolTable.push();

    ControlFlow flow = {};
    flow.type        = ControlFlowType::NewScope;
    mControlFlow.push_back(flow);
}

void TParseContext::endNestedScope()
{
    symbolTable.pop();
    popControlFlow();
}

void TParseContext::beginLoop(TLoopType loopType, const TSourceLoc &line)
{
    ControlFlow flow = {};
    flow.type        = ControlFlowType::Loop;
    mControlFlow.push_back(flow);

    checkNestingLevel(line);

    // According to ESSL 100 spec, Appendix A, while and do-while don't need to be supported.
    // WebGL forbids them, and so they must be rejected.
    if (mValidateESSL100Limitations && loopType != ELoopFor)
    {
        error(line, "This type of loop is not allowed", loopType == ELoopWhile ? "while" : "do");
    }
}

void TParseContext::onLoopConditionBegin(TIntermNode *init, const TSourceLoc &line)
{
    if (mValidateESSL100Limitations)
    {
        checkESSL100ForLoopInit(init, line);
    }

    // Make sure variables declared in |init| are scoped to the for loop in the IR.  This is to aid
    // generators distinguish between:
    //
    //     for (int i = 0; ...) { }
    //
    // and:
    //
    //     int i = 0;
    //     for (; ...) { }
    //
    // because they otherwise look identical in the IR.  The difference between the two is that in
    // the second case, |i| might be used after the `for` loop.  This rescoping of the variable is
    // purely an optimization; the IR would be able to tell if |i| is later used or not by visiting
    // the rest of the block, which is simply less efficient.
    if (init != nullptr)
    {
        TIntermDeclaration *declaration = init->getAsDeclarationNode();
        if (declaration != nullptr)
        {
            for (TIntermNode *singleDecl : *declaration->getSequence())
            {
                // Extract the symbol and scope it to the `for` loop.  All the `nullptr` checks here
                // are there to avoid crashes in the presence of compile errors.
                TIntermBinary *symbolInit = singleDecl->getAsBinaryNode();
                TIntermSymbol *symbol =
                    symbolInit != nullptr && symbolInit->getOp() == EOpInitialize
                        ? symbolInit->getLeft()->getAsSymbolNode()
                        : singleDecl->getAsSymbolNode();
                // The check makes sure sole struct declarations are skipped, like `struct S { ...
                // };` which the translator declares with an "empty" variable.  Same if init
                // expression is just `S;`.
                if (symbol != nullptr && symbol->variable().symbolType() != SymbolType::Empty)
                {
                    mIRBuilder.rescopeAsForLoopVariable(mVariableToId.at(&symbol->variable()).id);
                }
            }
        }
    }

    mIRBuilder.beginLoopCondition();
}

void TParseContext::onLoopConditionEnd(TIntermNode *condition, const TSourceLoc &line)
{
    if (mValidateESSL100Limitations)
    {
        checkESSL100ForLoopCondition(condition, line);
    }

    if (mCompileOptions.rejectWebglShadersWithUndefinedBehavior)
    {
        mControlFlow.back().loopLocation = line;
        TIntermConstantUnion *constCondition =
            condition ? condition->getAsConstantUnion() : nullptr;
        TIntermSymbol *conditionSymbol = condition ? condition->getAsSymbolNode() : nullptr;

        const bool isConditionConstantTrue =
            condition == nullptr ||
            (constCondition != nullptr && constCondition->getType().isScalarBool() &&
             constCondition->getBConst(0));

        if (isConditionConstantTrue)
        {
            mControlFlow.back().isLoopConditionConstantTrue = true;
        }
        else if (conditionSymbol != nullptr &&
                 mConstantTrueVariables.find(conditionSymbol->uniqueId()) !=
                     mConstantTrueVariables.end())
        {
            mControlFlow.back().loopConditionConstantTrueSymbol = &conditionSymbol->variable();
        }
    }

    if (condition == nullptr)
    {
        // If a condition is not specified, assume it's true (possible with for(..;;..)).
        mIRBuilder.pushConstantBool(true);
    }
    else if (condition->getAsDeclarationNode())
    {
        // If a condition is a variable declaration (like while (bool cond = ...)), push the
        // variable to the stack so it's loaded from.
        TIntermDeclaration *declaration = condition->getAsDeclarationNode();
        TIntermBinary *declarator       = declaration->getSequence()->front()->getAsBinaryNode();
        ASSERT(declarator->getLeft()->getAsSymbolNode());
        pushVariable(&declarator->getLeft()->getAsSymbolNode()->variable());
    }
    mIRBuilder.endLoopCondition();
}

void TParseContext::onLoopContinueEnd(TIntermNode *statement, const TSourceLoc &line)
{
    if (mValidateESSL100Limitations)
    {
        checkESSL100ForLoopContinue(statement, line);
    }

    mIRBuilder.endLoopContinue();
    endStatementWithValue(statement);
}

void TParseContext::onDoLoopBegin()
{
    mIRBuilder.beginDoLoop();
}

void TParseContext::onDoLoopConditionBegin()
{
    mIRBuilder.beginDoLoopCondition();
}

TIntermNode *TParseContext::addLoop(TLoopType type,
                                    TIntermNode *init,
                                    TIntermNode *cond,
                                    TIntermTyped *expr,
                                    TIntermNode *body,
                                    const TSourceLoc &line)
{
    popControlFlow();

    TIntermNode *node       = nullptr;
    TIntermTyped *typedCond = nullptr;
    if (cond)
    {
        markStaticUseIfSymbol(cond);
        typedCond = cond->getAsTyped();
    }
    if (expr)
    {
        markStaticUseIfSymbol(expr);
    }

    // In case the loop body was not parsed as a block and contains a statement that simply refers
    // to a variable, we need to mark it as statically used.
    if (body)
    {
        markStaticUseIfSymbol(body);
    }
    if (cond == nullptr || typedCond)
    {
        if (type == ELoopDoWhile && typedCond)
        {
            checkIsScalarBool(line, typedCond);
        }

        if (type == ELoopDoWhile)
        {
            mIRBuilder.endDoLoop();
        }
        else
        {
            mIRBuilder.endLoop();
        }

        // In the case of other loops, it was checked before that the condition is a scalar boolean.
        ASSERT(mDiagnostics->numErrors() > 0 || typedCond == nullptr ||
               (typedCond->getBasicType() == EbtBool && !typedCond->isArray() &&
                !typedCond->isVector()));

        node = new TIntermLoop(type, init, typedCond, expr, EnsureLoopBodyBlock(body));
        node->setLine(line);
        return node;
    }

    ASSERT(type != ELoopDoWhile);
    mIRBuilder.endLoop();

    TIntermDeclaration *declaration = cond->getAsDeclarationNode();
    ASSERT(declaration);
    TIntermBinary *declarator = declaration->getSequence()->front()->getAsBinaryNode();
    ASSERT(declarator->getLeft()->getAsSymbolNode());

    // The condition is a declaration. In the AST representation we don't support declarations as
    // loop conditions. Wrap the loop to a block that declares the condition variable and contains
    // the loop.
    TIntermBlock *block = new TIntermBlock();

    TIntermDeclaration *declareCondition = new TIntermDeclaration();
    declareCondition->appendDeclarator(declarator->getLeft()->deepCopy());
    block->appendStatement(declareCondition);

    TIntermBinary *conditionInit = new TIntermBinary(EOpAssign, declarator->getLeft()->deepCopy(),
                                                     declarator->getRight()->deepCopy());
    TIntermLoop *loop = new TIntermLoop(type, init, conditionInit, expr, EnsureLoopBodyBlock(body));
    block->appendStatement(loop);
    loop->setLine(line);
    block->setLine(line);
    return block;
}

void TParseContext::onIfTrueBlockBegin(TIntermTyped *cond, const TSourceLoc &loc)
{
    ControlFlow flow = {};
    flow.type        = ControlFlowType::If;
    mControlFlow.push_back(flow);

    checkIsScalarBool(loc, cond);
    mIRBuilder.beginIfTrueBlock();
}

void TParseContext::onIfTrueBlockEnd()
{
    mIRBuilder.endIfTrueBlock();
}

void TParseContext::onIfFalseBlockBegin()
{
    mIRBuilder.beginIfFalseBlock();
}

void TParseContext::onIfFalseBlockEnd()
{
    mIRBuilder.endIfFalseBlock();
}

TIntermNode *TParseContext::addIfElse(TIntermTyped *cond,
                                      TIntermNodePair code,
                                      const TSourceLoc &loc)
{
    popControlFlow();

    bool isScalarBool = checkIsScalarBool(loc, cond);
    // In case the conditional statements were not parsed as blocks and contain a statement that
    // simply refers to a variable, we need to mark them as statically used.
    if (code.node1)
    {
        markStaticUseIfSymbol(code.node1);
    }
    if (code.node2)
    {
        markStaticUseIfSymbol(code.node2);
    }

    mIRBuilder.endIf();

    // For compile time constant conditions, prune the code now.
    if (isScalarBool && cond->getAsConstantUnion())
    {
        if (cond->getAsConstantUnion()->getBConst(0) == true)
        {
            return EnsureBlock(code.node1);
        }
        else
        {
            return EnsureBlock(code.node2);
        }
    }

    TIntermIfElse *node = new TIntermIfElse(cond, EnsureBlock(code.node1), EnsureBlock(code.node2));
    markStaticUseIfSymbol(cond);
    node->setLine(loc);

    return node;
}

void TParseContext::addFullySpecifiedType(TPublicType *typeSpecifier)
{
    checkPrecisionSpecified(typeSpecifier->getLine(), typeSpecifier->precision,
                            typeSpecifier->getBasicType());

    if (mShaderVersion < 300 && typeSpecifier->isArray())
    {
        error(typeSpecifier->getLine(), "not supported", "first-class array");
        typeSpecifier->clearArrayness();
    }
}

TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder,
                                                 const TPublicType &typeSpecifier)
{
    TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);

    TPublicType returnType     = typeSpecifier;
    returnType.qualifier       = typeQualifier.qualifier;
    returnType.invariant       = typeQualifier.invariant;
    returnType.precise         = typeQualifier.precise;
    returnType.layoutQualifier = typeQualifier.layoutQualifier;
    returnType.memoryQualifier = typeQualifier.memoryQualifier;
    returnType.precision       = typeSpecifier.precision;

    if (typeQualifier.precision != EbpUndefined)
    {
        returnType.precision = typeQualifier.precision;
    }

    checkPrecisionSpecified(typeSpecifier.getLine(), returnType.precision,
                            typeSpecifier.getBasicType());

    checkInvariantVariableQualifier(returnType.invariant, returnType.qualifier,
                                    typeSpecifier.getLine());

    checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), returnType.layoutQualifier);

    checkEarlyFragmentTestsIsNotSpecified(typeSpecifier.getLine(),
                                          returnType.layoutQualifier.earlyFragmentTests);

    switch (returnType.qualifier)
    {
        case EvqSmooth:
        case EvqFlat:
        case EvqNoPerspective:
        case EvqCentroid:
        case EvqSample:
        case EvqNoPerspectiveCentroid:
        case EvqNoPerspectiveSample:
            // These qualifiers must be merged with |in| or |out| qualifiers.
            error(typeSpecifier.getLine(), "qualifier can only be used with in and out variables",
                  getQualifierString(returnType.qualifier));
            break;

        case EvqSampleIn:
        case EvqSampleOut:
        case EvqNoPerspectiveSampleIn:
        case EvqNoPerspectiveSampleOut:
            mSampleQualifierSpecified = true;
            break;
        default:
            break;
    }

    if (mShaderVersion < 300)
    {
        if (typeSpecifier.isArray())
        {
            error(typeSpecifier.getLine(), "not supported", "first-class array");
            returnType.clearArrayness();
        }

        if (returnType.qualifier == EvqAttribute &&
            (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
        {
            error(typeSpecifier.getLine(), "cannot be bool or int",
                  getQualifierString(returnType.qualifier));
        }

        if ((returnType.qualifier == EvqVaryingIn || returnType.qualifier == EvqVaryingOut) &&
            (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
        {
            error(typeSpecifier.getLine(), "cannot be bool or int",
                  getQualifierString(returnType.qualifier));
        }
    }
    else
    {
        if (!returnType.layoutQualifier.isEmpty())
        {
            checkIsAtGlobalLevel(typeSpecifier.getLine(), "layout");
        }
        if (sh::IsVarying(returnType.qualifier) || returnType.qualifier == EvqVertexIn ||
            returnType.qualifier == EvqFragmentOut || returnType.qualifier == EvqFragmentInOut)
        {
            checkInputOutputTypeIsValidES3(returnType.qualifier, typeSpecifier,
                                           typeSpecifier.getLine());
        }
        if (returnType.qualifier == EvqComputeIn)
        {
            error(typeSpecifier.getLine(), "'in' can only be used to specify the local group size",
                  "in");
        }
    }

    return returnType;
}

void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier,
                                                   const TPublicType &type,
                                                   const TSourceLoc &qualifierLocation)
{
    // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
    if (type.getBasicType() == EbtBool)
    {
        error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
    }

    // Specific restrictions apply for vertex shader inputs and fragment shader outputs.
    switch (qualifier)
    {
        case EvqVertexIn:
            // ESSL 3.00 section 4.3.4
            if (type.isArray())
            {
                error(qualifierLocation, "cannot be array", getQualifierString(qualifier));
            }
            // Vertex inputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
            return;
        case EvqFragmentOut:
        case EvqFragmentInOut:
            // ESSL 3.00 section 4.3.6
            if (type.typeSpecifierNonArray.isMatrix())
            {
                error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
            }
            // Fragment outputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
            return;
        default:
            break;
    }

    // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of
    // restrictions.
    bool typeContainsIntegers =
        (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt ||
         type.isStructureContainingType(EbtInt) || type.isStructureContainingType(EbtUInt));
    bool extendedShaderTypes = mShaderVersion >= 320 ||
                               isExtensionEnabled(TExtension::EXT_geometry_shader) ||
                               isExtensionEnabled(TExtension::OES_geometry_shader) ||
                               isExtensionEnabled(TExtension::EXT_tessellation_shader) ||
                               isExtensionEnabled(TExtension::OES_tessellation_shader);
    if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut &&
        (!extendedShaderTypes || mShaderType == GL_FRAGMENT_SHADER))
    {
        error(qualifierLocation, "must use 'flat' interpolation here",
              getQualifierString(qualifier));
    }

    if (type.getBasicType() == EbtStruct)
    {
        // ESSL 3.00 sections 4.3.4 and 4.3.6.
        // These restrictions are only implied by the ESSL 3.00 spec, but
        // the ESSL 3.10 spec lists these restrictions explicitly.
        if (type.isArray())
        {
            error(qualifierLocation, "cannot be an array of structures",
                  getQualifierString(qualifier));
        }
        if (type.isStructureContainingArrays())
        {
            error(qualifierLocation, "cannot be a structure containing an array",
                  getQualifierString(qualifier));
        }
        if (type.isStructureContainingType(EbtStruct))
        {
            error(qualifierLocation, "cannot be a structure containing a structure",
                  getQualifierString(qualifier));
        }
        if (type.isStructureContainingType(EbtBool))
        {
            error(qualifierLocation, "cannot be a structure containing a bool",
                  getQualifierString(qualifier));
        }
    }
}

void TParseContext::checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier)
{
    if (qualifier.getType() == QtStorage)
    {
        const TStorageQualifierWrapper &storageQualifier =
            static_cast<const TStorageQualifierWrapper &>(qualifier);
        if (!declaringFunction() && storageQualifier.getQualifier() != EvqConst &&
            !symbolTable.atGlobalLevel())
        {
            error(storageQualifier.getLine(),
                  "Local variables can only use the const storage qualifier.",
                  storageQualifier.getQualifierString());
        }
    }
}

void TParseContext::checkMemoryQualifierIsNotSpecified(const TMemoryQualifier &memoryQualifier,
                                                       const TSourceLoc &location)
{
    const std::string reason(
        "Only allowed with shader storage blocks, variables declared within shader storage blocks "
        "and variables declared as image types.");
    if (memoryQualifier.readonly)
    {
        error(location, reason.c_str(), "readonly");
    }
    if (memoryQualifier.writeonly)
    {
        error(location, reason.c_str(), "writeonly");
    }
    if (memoryQualifier.coherent)
    {
        error(location, reason.c_str(), "coherent");
    }
    if (memoryQualifier.restrictQualifier)
    {
        error(location, reason.c_str(), "restrict");
    }
    if (memoryQualifier.volatileQualifier)
    {
        error(location, reason.c_str(), "volatile");
    }
}

// Make sure there is no offset overlapping, and store the newly assigned offset to "type" in
// intermediate tree.
void TParseContext::checkAtomicCounterOffsetDoesNotOverlap(bool forceAppend,
                                                           const TSourceLoc &loc,
                                                           TType *type)
{
    const size_t size = type->isArray() ? kAtomicCounterArrayStride * type->getArraySizeProduct()
                                        : kAtomicCounterSize;
    TLayoutQualifier layoutQualifier = type->getLayoutQualifier();
    auto &bindingState               = mAtomicCounterBindingStates[layoutQualifier.binding];
    int offset;
    if (layoutQualifier.offset == -1 || forceAppend)
    {
        offset = bindingState.appendSpan(size);
    }
    else
    {
        offset = bindingState.insertSpan(layoutQualifier.offset, size);
    }
    if (offset == -1)
    {
        error(loc, "Offset overlapping", "atomic counter");
        return;
    }
    layoutQualifier.offset = offset;
    type->setLayoutQualifier(layoutQualifier);
}

void TParseContext::checkAtomicCounterOffsetAlignment(const TSourceLoc &location, const TType &type)
{
    TLayoutQualifier layoutQualifier = type.getLayoutQualifier();

    // OpenGL ES 3.1 Table 6.5, Atomic counter offset must be a multiple of 4
    if (layoutQualifier.offset % 4 != 0)
    {
        error(location, "Offset must be multiple of 4", "atomic counter");
    }
}

void TParseContext::checkAtomicCounterOffsetLimit(const TSourceLoc &location, const TType &type)
{
    TLayoutQualifier layoutQualifier = type.getLayoutQualifier();

    if (layoutQualifier.offset >= mResources.MaxAtomicCounterBufferSize)
    {
        error(location, "Offset must not exceed the maximum atomic counter buffer size",
              "atomic counter");
    }
}

void TParseContext::checkAtomicCounterOffsetIsValid(bool forceAppend,
                                                    const TSourceLoc &loc,
                                                    TType *type)
{
    checkAtomicCounterOffsetDoesNotOverlap(forceAppend, loc, type);
    checkAtomicCounterOffsetAlignment(loc, *type);
    checkAtomicCounterOffsetLimit(loc, *type);
}

void TParseContext::checkGeometryShaderInputAndSetArraySize(const TSourceLoc &location,
                                                            const ImmutableString &token,
                                                            TType *type,
                                                            GeomTessArray *sizedOut)
{
    if (type->getQualifier() == EvqPerVertexIn && mShaderType == GL_GEOMETRY_SHADER)
    {
        // This is a redeclaration of gl_in, which may be unsized.
        if (!type->isArray())
        {
            error(location, "gl_in must be an array", "gl_in");
            type->makeArray(0);
        }

        // If the size is already determined, set the size / verify it:
        if (mGeometryShaderInputPrimitiveType != EptUndefined)
        {
            ASSERT(mGeometryInputArraySize != 0);
            if (type->getOutermostArraySize() > 0 &&
                type->getOutermostArraySize() != mGeometryInputArraySize)
            {
                error(location, "gl_in array size inconsistent with primitive", "gl_in");
            }
            else if (type->getOutermostArraySize() == 0)
            {
                type->sizeOutermostUnsizedArray(mGeometryInputArraySize);
            }
        }
        else
        {
            warning(location,
                    "Missing a valid input primitive declaration before declaring an unsized "
                    "gl_in array",
                    "Deferred");
            mDeferredArrayTypesToSize.push_back(type);
            *sizedOut = GeomTessArray::Deferred;
        }
    }
    else if (IsGeometryShaderInput(mShaderType, type->getQualifier()))
    {
        if (type->isArray() && type->getOutermostArraySize() == 0u)
        {
            // Set size for the unsized geometry shader inputs if they are declared after a valid
            // input primitive declaration.
            if (mGeometryShaderInputPrimitiveType != EptUndefined)
            {
                ASSERT(symbolTable.getGlInVariableWithArraySize() != nullptr);
                type->sizeOutermostUnsizedArray(
                    symbolTable.getGlInVariableWithArraySize()->getType().getOutermostArraySize());
            }
            else
            {
                // [GLSL ES 3.2 SPEC Chapter 4.4.1.2]
                // An input can be declared without an array size if there is a previous layout
                // which specifies the size.
                warning(location,
                        "Missing a valid input primitive declaration before declaring an unsized "
                        "array input",
                        "Deferred");
                mDeferredArrayTypesToSize.push_back(type);
                *sizedOut = GeomTessArray::Deferred;
            }
        }
        else if (type->isArray())
        {
            setGeometryShaderInputArraySize(type->getOutermostArraySize(), location);
        }
        else
        {
            error(location, "Geometry shader input variable must be declared as an array", token);
        }
    }
}

void TParseContext::checkTessellationShaderUnsizedArraysAndSetSize(const TSourceLoc &location,
                                                                   const ImmutableString &token,
                                                                   TType *type,
                                                                   GeomTessArray *sizedOut)
{
    TQualifier qualifier = type->getQualifier();

    if (qualifier == EvqPerVertexIn && type->isArray() &&
        (mShaderType == GL_TESS_CONTROL_SHADER || mShaderType == GL_TESS_EVALUATION_SHADER))
    {
        // gl_in in both tessellation stages should be sized as gl_MaxPatchVertices
        if (type->getOutermostArraySize() == 0)
        {
            ASSERT(mResources.MaxPatchVertices > 0);
            type->sizeOutermostUnsizedArray(mResources.MaxPatchVertices);
        }
        else if (type->getOutermostArraySize() !=
                 static_cast<unsigned int>(mResources.MaxPatchVertices))
        {
            error(location,
                  "If a size is specified for a tessellation control or evaluation gl_in "
                  "variable, it must match the maximum patch size (gl_MaxPatchVertices).",
                  token);
        }
        return;
    }
    if (qualifier == EvqPerVertexOut && type->isArray() && mShaderType == GL_TESS_CONTROL_SHADER)
    {
        if (type->getOutermostArraySize() == 0)
        {
            if (mTessControlShaderOutputVertices == 0)
            {
                error(location,
                      "Missing a valid vertices declaration before declaring an unsized "
                      "gl_out array",
                      "gl_out");
            }
            else
            {
                type->sizeOutermostUnsizedArray(mTessControlShaderOutputVertices);
            }
        }
        else if (type->getOutermostArraySize() !=
                     static_cast<unsigned int>(mTessControlShaderOutputVertices) &&
                 mTessControlShaderOutputVertices != 0)
        {
            error(location,
                  "If a size is specified for a tessellation control gl_out "
                  "variable, it must match the the number of vertices in the output patch.",
                  token);
        }
        return;
    }

    if (!IsTessellationControlShaderOutput(mShaderType, qualifier) &&
        !IsTessellationControlShaderInput(mShaderType, qualifier) &&
        !IsTessellationEvaluationShaderInput(mShaderType, qualifier))
    {
        return;
    }

    // Such variables must be declared as arrays or inside output blocks declared as arrays.
    if (!type->isArray())
    {
        error(location, "Tessellation interface variables must be declared as an array", token);
        return;
    }

    // If a size is specified, it must match the maximum patch size.
    unsigned int outermostSize = type->getOutermostArraySize();
    if (outermostSize == 0u)
    {
        switch (qualifier)
        {
            case EvqTessControlIn:
            case EvqTessEvaluationIn:
            case EvqSmoothIn:
            case EvqFlatIn:
            case EvqNoPerspectiveIn:
            case EvqCentroidIn:
            case EvqSampleIn:
            case EvqNoPerspectiveCentroidIn:
            case EvqNoPerspectiveSampleIn:
                // Declaring an array size is optional. If no size is specified, it will be taken
                // from the implementation-dependent maximum patch size (gl_MaxPatchVertices).
                ASSERT(mResources.MaxPatchVertices > 0);
                type->sizeOutermostUnsizedArray(mResources.MaxPatchVertices);
                break;
            case EvqTessControlOut:
            case EvqTessEvaluationOut:
            case EvqSmoothOut:
            case EvqFlatOut:
            case EvqNoPerspectiveOut:
            case EvqCentroidOut:
            case EvqSampleOut:
            case EvqNoPerspectiveCentroidOut:
            case EvqNoPerspectiveSampleOut:
                // Declaring an array size is optional. If no size is specified, it will be taken
                // from output patch size declared in the shader.  If the patch size is not yet
                // declared, this is deferred until such time as it does.
                if (mTessControlShaderOutputVertices == 0)
                {
                    mDeferredArrayTypesToSize.push_back(type);
                    *sizedOut = GeomTessArray::Deferred;
                }
                else
                {
                    type->sizeOutermostUnsizedArray(mTessControlShaderOutputVertices);
                }
                break;
            default:
                UNREACHABLE();
                break;
        }
        return;
    }

    if (IsTessellationControlShaderInput(mShaderType, qualifier) ||
        IsTessellationEvaluationShaderInput(mShaderType, qualifier))
    {
        if (outermostSize != static_cast<unsigned int>(mResources.MaxPatchVertices))
        {
            error(location,
                  "If a size is specified for a tessellation control or evaluation user-defined "
                  "input variable, it must match the maximum patch size (gl_MaxPatchVertices).",
                  token);
        }
    }
    else if (IsTessellationControlShaderOutput(mShaderType, qualifier))
    {
        if (outermostSize != static_cast<unsigned int>(mTessControlShaderOutputVertices) &&
            mTessControlShaderOutputVertices != 0)
        {
            error(location,
                  "If a size is specified for a tessellation control user-defined per-vertex "
                  "output variable, it must match the the number of vertices in the output "
                  "patch.",
                  token);
        }
    }
}

TIntermDeclaration *TParseContext::parseSingleDeclaration(
    TPublicType &publicType,
    const TSourceLoc &identifierOrTypeLocation,
    const ImmutableString &identifier)
{
    TType *type = new TType(publicType);
    if ((mCompileOptions.flattenPragmaSTDGLInvariantAll || mCompileOptions.useIR) &&
        mDirectiveHandler.pragma().stdgl.invariantAll)
    {
        TQualifier qualifier = type->getQualifier();

        // The directive handler has already taken care of rejecting invalid uses of this pragma
        // (for example, in ESSL 3.00 fragment shaders), so at this point, flatten it into all
        // affected variable declarations:
        //
        // 1. Built-in special variables which are inputs to the fragment shader. (These are handled
        // elsewhere, in TranslatorGLSL.)
        //
        // 2. Outputs from vertex shaders in ESSL 1.00 and 3.00 (EvqVaryingOut and EvqVertexOut). It
        // is actually less likely that there will be bugs in the handling of ESSL 3.00 shaders, but
        // the way this is currently implemented we have to enable this compiler option before
        // parsing the shader and determining the shading language version it uses. If this were
        // implemented as a post-pass, the workaround could be more targeted.
        if (qualifier == EvqVaryingOut || qualifier == EvqVertexOut)
        {
            type->setInvariant(true);
        }
    }

    if (identifier == "gl_FragDepth")
    {
        if (type->getQualifier() == EvqFragmentOut)
        {
            type->setQualifier(EvqFragDepth);
        }
        else
        {
            error(identifierOrTypeLocation,
                  "gl_FragDepth can only be redeclared as fragment output", identifier);
        }
    }

    GeomTessArray sized = GeomTessArray::Sized;
    checkGeometryShaderInputAndSetArraySize(identifierOrTypeLocation, identifier, type, &sized);
    checkTessellationShaderUnsizedArraysAndSetSize(identifierOrTypeLocation, identifier, type,
                                                   &sized);
    if (sized == GeomTessArray::Sized)
    {
        type->setTypeId(getTypeId(*type));
    }

    declarationQualifierErrorCheck(type->getQualifier(), publicType.layoutQualifier,
                                   identifierOrTypeLocation);

    bool emptyDeclaration                  = (identifier == "");
    mDeferredNonEmptyDeclarationErrorCheck = emptyDeclaration;

    TIntermSymbol *symbol = nullptr;
    if (emptyDeclaration)
    {
        emptyDeclarationErrorCheck(*type, identifierOrTypeLocation);
        // In most cases we don't need to create a symbol node for an empty declaration.
        // But if the empty declaration is declaring a struct type, the symbol node will store that.
        if (type->getBasicType() == EbtStruct)
        {
            TVariable *emptyVariable =
                new TVariable(&symbolTable, kEmptyImmutableString, type, SymbolType::Empty);
            symbol = new TIntermSymbol(emptyVariable);
        }
        else if (IsAtomicCounter(publicType.getBasicType()))
        {
            setAtomicCounterBindingDefaultOffset(publicType, identifierOrTypeLocation);
        }
    }
    else
    {
        nonEmptyDeclarationErrorCheck(publicType, identifierOrTypeLocation);

        checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, type);
        checkDeclarationIsValidArraySize(identifierOrTypeLocation, identifier, type);

        if (IsAtomicCounter(type->getBasicType()))
        {
            checkAtomicCounterOffsetIsValid(false, identifierOrTypeLocation, type);
        }

        adjustRedeclaredBuiltInType(identifierOrTypeLocation, identifier, type);

        TVariable *variable = nullptr;
        if (declareVariable(identifierOrTypeLocation, identifier, type, sized, &variable))
        {
            symbol = new TIntermSymbol(variable);
        }
    }

    TIntermDeclaration *declaration = new TIntermDeclaration();
    declaration->setLine(identifierOrTypeLocation);
    if (symbol)
    {
        symbol->setLine(identifierOrTypeLocation);
        declaration->appendDeclarator(symbol);
    }
    return declaration;
}

TIntermDeclaration *TParseContext::parseSingleArrayDeclaration(
    TPublicType &elementType,
    const TSourceLoc &identifierLocation,
    const ImmutableString &identifier,
    const TSourceLoc &indexLocation,
    const TVector<unsigned int> &arraySizes)
{
    mDeferredNonEmptyDeclarationErrorCheck = false;

    declarationQualifierErrorCheck(elementType.qualifier, elementType.layoutQualifier,
                                   identifierLocation);

    nonEmptyDeclarationErrorCheck(elementType, identifierLocation);

    checkIsValidTypeAndQualifierForArray(indexLocation, elementType);

    TType *arrayType = new TType(elementType);
    arrayType->makeArrays(arraySizes);

    checkArrayOfArraysInOut(indexLocation, elementType, *arrayType);

    GeomTessArray sized = GeomTessArray::Sized;
    checkGeometryShaderInputAndSetArraySize(indexLocation, identifier, arrayType, &sized);
    checkTessellationShaderUnsizedArraysAndSetSize(indexLocation, identifier, arrayType, &sized);

    checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, arrayType);
    checkDeclarationIsValidArraySize(identifierLocation, identifier, arrayType);

    if (IsAtomicCounter(arrayType->getBasicType()))
    {
        checkAtomicCounterOffsetIsValid(false, identifierLocation, arrayType);
    }

    adjustRedeclaredBuiltInType(identifierLocation, identifier, arrayType);
    if (sized == GeomTessArray::Sized)
    {
        arrayType->setTypeId(getTypeId(*arrayType));
    }

    TIntermDeclaration *declaration = new TIntermDeclaration();
    declaration->setLine(identifierLocation);

    TVariable *variable = nullptr;
    if (declareVariable(identifierLocation, identifier, arrayType, sized, &variable))
    {
        TIntermSymbol *symbol = new TIntermSymbol(variable);
        symbol->setLine(identifierLocation);
        declaration->appendDeclarator(symbol);
    }

    return declaration;
}

TIntermDeclaration *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
                                                              const TSourceLoc &identifierLocation,
                                                              const ImmutableString &identifier,
                                                              const TSourceLoc &initLocation,
                                                              TIntermTyped *initializer)
{
    mDeferredNonEmptyDeclarationErrorCheck = false;

    declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
                                   identifierLocation);

    nonEmptyDeclarationErrorCheck(publicType, identifierLocation);

    TIntermDeclaration *declaration = new TIntermDeclaration();
    declaration->setLine(identifierLocation);

    TIntermBinary *initNode = nullptr;
    TType *type             = new TType(publicType);
    if (executeInitializer(identifierLocation, identifier, type, initializer, &initNode))
    {
        if (initNode)
        {
            declaration->appendDeclarator(initNode);
        }
        else if (publicType.isStructSpecifier())
        {
            // The initialization got constant folded.  If it's a struct, declare the struct anyway.
            TVariable *emptyVariable =
                new TVariable(&symbolTable, kEmptyImmutableString, type, SymbolType::Empty);
            TIntermSymbol *symbol = new TIntermSymbol(emptyVariable);
            symbol->setLine(publicType.getLine());
            declaration->appendDeclarator(symbol);
        }
    }
    return declaration;
}

TIntermDeclaration *TParseContext::parseSingleArrayInitDeclaration(
    TPublicType &elementType,
    const TSourceLoc &identifierLocation,
    const ImmutableString &identifier,
    const TSourceLoc &indexLocation,
    const TVector<unsigned int> &arraySizes,
    const TSourceLoc &initLocation,
    TIntermTyped *initializer)
{
    mDeferredNonEmptyDeclarationErrorCheck = false;

    declarationQualifierErrorCheck(elementType.qualifier, elementType.layoutQualifier,
                                   identifierLocation);

    nonEmptyDeclarationErrorCheck(elementType, identifierLocation);

    checkIsValidTypeAndQualifierForArray(indexLocation, elementType);

    TType *arrayType = new TType(elementType);
    arrayType->makeArrays(arraySizes);

    TIntermDeclaration *declaration = new TIntermDeclaration();
    declaration->setLine(identifierLocation);

    // initNode will correspond to the whole of "type b[n] = initializer".
    TIntermBinary *initNode = nullptr;
    if (executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
    {
        if (initNode)
        {
            declaration->appendDeclarator(initNode);
        }
    }

    return declaration;
}

TIntermGlobalQualifierDeclaration *TParseContext::parseGlobalQualifierDeclaration(
    const TTypeQualifierBuilder &typeQualifierBuilder,
    const TSourceLoc &identifierLoc,
    const ImmutableString &identifier,
    const TSymbol *symbol)
{
    TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);

    if (!typeQualifier.invariant && !typeQualifier.precise)
    {
        error(identifierLoc, "Expected invariant or precise", identifier);
        return nullptr;
    }
    if (typeQualifier.invariant && !checkIsAtGlobalLevel(identifierLoc, "invariant varying"))
    {
        return nullptr;
    }
    if (!symbol)
    {
        error(identifierLoc, "undeclared identifier declared as invariant or precise", identifier);
        return nullptr;
    }
    if (!IsQualifierUnspecified(typeQualifier.qualifier))
    {
        error(identifierLoc, "invariant or precise declaration specifies qualifier",
              getQualifierString(typeQualifier.qualifier));
    }
    if (typeQualifier.precision != EbpUndefined)
    {
        error(identifierLoc, "invariant or precise declaration specifies precision",
              getPrecisionString(typeQualifier.precision));
    }
    if (!typeQualifier.layoutQualifier.isEmpty())
    {
        error(identifierLoc, "invariant or precise declaration specifies layout", "'layout'");
    }

    const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
    if (!variable)
    {
        return nullptr;
    }
    const TType &type = variable->getType();

    checkInvariantVariableQualifier(typeQualifier.invariant, type.getQualifier(),
                                    typeQualifier.line);
    checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);

    if (typeQualifier.invariant)
    {
        symbolTable.addInvariantVarying(*variable);
    }

    TIntermSymbol *intermSymbol = new TIntermSymbol(variable);
    intermSymbol->setLine(identifierLoc);

    mBuiltInQualified[type.getQualifier()] = true;

    const ir::VariableId id = declareBuiltInOnFirstUse(variable);
    if (typeQualifier.invariant)
    {
        mIRBuilder.markVariableInvariant(id);
    }
    if (typeQualifier.precise)
    {
        mIRBuilder.markVariablePrecise(id);
    }

    return new TIntermGlobalQualifierDeclaration(intermSymbol, typeQualifier.precise,
                                                 identifierLoc);
}

void TParseContext::parseDeclarator(TPublicType &publicType,
                                    const TSourceLoc &identifierLocation,
                                    const ImmutableString &identifier,
                                    TIntermDeclaration *declarationOut)
{
    // If the declaration starting this declarator list was empty (example: int,), some checks were
    // not performed.
    if (mDeferredNonEmptyDeclarationErrorCheck)
    {
        nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
        mDeferredNonEmptyDeclarationErrorCheck = false;
    }

    checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);

    TType *type = new TType(publicType);

    GeomTessArray sized = GeomTessArray::Sized;
    checkGeometryShaderInputAndSetArraySize(identifierLocation, identifier, type, &sized);
    checkTessellationShaderUnsizedArraysAndSetSize(identifierLocation, identifier, type, &sized);

    checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, type);
    checkDeclarationIsValidArraySize(identifierLocation, identifier, type);

    if (IsAtomicCounter(type->getBasicType()))
    {
        checkAtomicCounterOffsetIsValid(true, identifierLocation, type);
    }

    adjustRedeclaredBuiltInType(identifierLocation, identifier, type);
    if (sized == GeomTessArray::Sized)
    {
        type->setTypeId(getTypeId(*type));
    }

    TVariable *variable = nullptr;
    if (declareVariable(identifierLocation, identifier, type, sized, &variable))
    {
        TIntermSymbol *symbol = new TIntermSymbol(variable);
        symbol->setLine(identifierLocation);
        declarationOut->appendDeclarator(symbol);
    }
}

void TParseContext::parseArrayDeclarator(TPublicType &elementType,
                                         const TSourceLoc &identifierLocation,
                                         const ImmutableString &identifier,
                                         const TSourceLoc &arrayLocation,
                                         const TVector<unsigned int> &arraySizes,
                                         TIntermDeclaration *declarationOut)
{
    // If the declaration starting this declarator list was empty (example: int,), some checks were
    // not performed.
    if (mDeferredNonEmptyDeclarationErrorCheck)
    {
        nonEmptyDeclarationErrorCheck(elementType, identifierLocation);
        mDeferredNonEmptyDeclarationErrorCheck = false;
    }

    checkDeclaratorLocationIsNotSpecified(identifierLocation, elementType);

    if (checkIsValidTypeAndQualifierForArray(arrayLocation, elementType))
    {
        TType *arrayType = new TType(elementType);
        arrayType->makeArrays(arraySizes);

        GeomTessArray sized = GeomTessArray::Sized;
        checkGeometryShaderInputAndSetArraySize(identifierLocation, identifier, arrayType, &sized);
        checkTessellationShaderUnsizedArraysAndSetSize(identifierLocation, identifier, arrayType,
                                                       &sized);

        checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, arrayType);
        checkDeclarationIsValidArraySize(identifierLocation, identifier, arrayType);

        if (IsAtomicCounter(arrayType->getBasicType()))
        {
            checkAtomicCounterOffsetDoesNotOverlap(true, identifierLocation, arrayType);

            checkAtomicCounterOffsetAlignment(identifierLocation, *arrayType);
        }

        adjustRedeclaredBuiltInType(identifierLocation, identifier, arrayType);
        if (sized == GeomTessArray::Sized)
        {
            arrayType->setTypeId(getTypeId(*arrayType));
        }

        TVariable *variable = nullptr;
        if (declareVariable(identifierLocation, identifier, arrayType, sized, &variable))
        {
            TIntermSymbol *symbol = new TIntermSymbol(variable);
            symbol->setLine(identifierLocation);
            declarationOut->appendDeclarator(symbol);
        }
    }
}

void TParseContext::parseInitDeclarator(const TPublicType &publicType,
                                        const TSourceLoc &identifierLocation,
                                        const ImmutableString &identifier,
                                        const TSourceLoc &initLocation,
                                        TIntermTyped *initializer,
                                        TIntermDeclaration *declarationOut)
{
    // If the declaration starting this declarator list was empty (example: int,), some checks were
    // not performed.
    if (mDeferredNonEmptyDeclarationErrorCheck)
    {
        nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
        mDeferredNonEmptyDeclarationErrorCheck = false;
    }

    checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);

    TIntermBinary *initNode = nullptr;
    TType *type             = new TType(publicType);
    if (executeInitializer(identifierLocation, identifier, type, initializer, &initNode))
    {
        //
        // build the intermediate representation
        //
        if (initNode)
        {
            declarationOut->appendDeclarator(initNode);
        }
    }
}

void TParseContext::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)
{
    // If the declaration starting this declarator list was empty (example: int,), some checks were
    // not performed.
    if (mDeferredNonEmptyDeclarationErrorCheck)
    {
        nonEmptyDeclarationErrorCheck(elementType, identifierLocation);
        mDeferredNonEmptyDeclarationErrorCheck = false;
    }

    checkDeclaratorLocationIsNotSpecified(identifierLocation, elementType);

    checkIsValidTypeAndQualifierForArray(indexLocation, elementType);

    TType *arrayType = new TType(elementType);
    arrayType->makeArrays(arraySizes);

    // initNode will correspond to the whole of "b[n] = initializer".
    TIntermBinary *initNode = nullptr;
    if (executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
    {
        if (initNode)
        {
            declarationOut->appendDeclarator(initNode);
        }
    }
}

TIntermNode *TParseContext::addEmptyStatement(const TSourceLoc &location)
{
    // It's simpler to parse an empty statement as a constant expression rather than having a
    // different type of node just for empty statements, that will be pruned from the AST anyway.
    TIntermNode *node = CreateZeroNode(TType(EbtInt, EbpMedium));
    node->setLine(location);
    // Because the node that is pushed has a value, appendStatement will expect to pop something
    // from the stack.  So push the same bogus value to the IR too.
    mIRBuilder.pushConstantInt(0);
    return node;
}

void TParseContext::setAtomicCounterBindingDefaultOffset(const TPublicType &publicType,
                                                         const TSourceLoc &location)
{
    const TLayoutQualifier &layoutQualifier = publicType.layoutQualifier;
    checkAtomicCounterBindingIsValid(location, layoutQualifier.binding);
    if (layoutQualifier.binding == -1 || layoutQualifier.offset == -1)
    {
        error(location, "Requires both binding and offset", "layout");
        return;
    }
    mAtomicCounterBindingStates[layoutQualifier.binding].setDefaultOffset(layoutQualifier.offset);
}

void TParseContext::parseDefaultPrecisionQualifier(const TPrecision precision,
                                                   const TPublicType &type,
                                                   const TSourceLoc &loc)
{
    if (!CanSetDefaultPrecisionOnType(type))
    {
        error(loc, "illegal type argument for default precision qualifier",
              getBasicString(type.getBasicType()));
        return;
    }
    symbolTable.setDefaultPrecision(type.getBasicType(), precision);
}

bool TParseContext::checkPrimitiveTypeMatchesTypeQualifier(const TTypeQualifier &typeQualifier)
{
    switch (typeQualifier.layoutQualifier.primitiveType)
    {
        case EptLines:
        case EptLinesAdjacency:
        case EptTriangles:
        case EptTrianglesAdjacency:
            return typeQualifier.qualifier == EvqGeometryIn;

        case EptLineStrip:
        case EptTriangleStrip:
            return typeQualifier.qualifier == EvqGeometryOut;

        case EptPoints:
            return true;

        default:
            UNREACHABLE();
            return false;
    }
}

void TParseContext::setGeometryShaderInputArraySize(unsigned int inputArraySize,
                                                    const TSourceLoc &line)
{
    if (!symbolTable.setGlInArraySize(inputArraySize, getShaderVersion()))
    {
        error(line,
              "Array size or input primitive declaration doesn't match the size of earlier sized "
              "array inputs.",
              "layout");
    }
    mGeometryInputArraySize = inputArraySize;
}

bool TParseContext::parseGeometryShaderInputLayoutQualifier(const TTypeQualifier &typeQualifier)
{
    ASSERT(typeQualifier.qualifier == EvqGeometryIn);

    const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier;

    if (layoutQualifier.maxVertices != -1)
    {
        error(typeQualifier.line,
              "max_vertices can only be declared in 'out' layout in a geometry shader", "layout");
        return false;
    }

    // Set mGeometryInputPrimitiveType if exists
    if (layoutQualifier.primitiveType != EptUndefined)
    {
        if (!checkPrimitiveTypeMatchesTypeQualifier(typeQualifier))
        {
            error(typeQualifier.line, "invalid primitive type for 'in' layout", "layout");
            return false;
        }

        if (mGeometryShaderInputPrimitiveType == EptUndefined)
        {
            mGeometryShaderInputPrimitiveType = layoutQualifier.primitiveType;
            const GLuint inputArraySize =
                GetGeometryShaderInputArraySize(mGeometryShaderInputPrimitiveType);

            // Size any implicitly sized arrays that have already been declared.  Done before
            // verifying gl_in's array size, since that could also need to be sized.
            sizeUnsizedArrayTypes(inputArraySize);
            setGeometryShaderInputArraySize(inputArraySize, typeQualifier.line);

            mIRBuilder.setGsPrimitiveIn(mGeometryShaderInputPrimitiveType);
        }
        else if (mGeometryShaderInputPrimitiveType != layoutQualifier.primitiveType)
        {
            error(typeQualifier.line, "primitive doesn't match earlier input primitive declaration",
                  "layout");
            return false;
        }
    }

    // Set mGeometryInvocations if exists
    if (layoutQualifier.invocations > 0)
    {
        if (mGeometryShaderInvocations == 0)
        {
            mGeometryShaderInvocations = layoutQualifier.invocations;
            mIRBuilder.setGsInvocations(mGeometryShaderInvocations);
        }
        else if (mGeometryShaderInvocations != layoutQualifier.invocations)
        {
            error(typeQualifier.line, "invocations contradicts to the earlier declaration",
                  "layout");
            return false;
        }
    }

    return true;
}

bool TParseContext::parseGeometryShaderOutputLayoutQualifier(const TTypeQualifier &typeQualifier)
{
    ASSERT(typeQualifier.qualifier == EvqGeometryOut);

    const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier;

    if (layoutQualifier.invocations > 0)
    {
        error(typeQualifier.line,
              "invocations can only be declared in 'in' layout in a geometry shader", "layout");
        return false;
    }

    // Set mGeometryOutputPrimitiveType if exists
    if (layoutQualifier.primitiveType != EptUndefined)
    {
        if (!checkPrimitiveTypeMatchesTypeQualifier(typeQualifier))
        {
            error(typeQualifier.line, "invalid primitive type for 'out' layout", "layout");
            return false;
        }

        if (mGeometryShaderOutputPrimitiveType == EptUndefined)
        {
            mGeometryShaderOutputPrimitiveType = layoutQualifier.primitiveType;
            mIRBuilder.setGsPrimitiveOut(mGeometryShaderOutputPrimitiveType);
        }
        else if (mGeometryShaderOutputPrimitiveType != layoutQualifier.primitiveType)
        {
            error(typeQualifier.line,
                  "primitive doesn't match earlier output primitive declaration", "layout");
            return false;
        }
    }

    // Set mGeometryMaxVertices if exists
    if (layoutQualifier.maxVertices > -1)
    {
        if (mGeometryShaderMaxVertices == -1)
        {
            mGeometryShaderMaxVertices = layoutQualifier.maxVertices;
            mIRBuilder.setGsMaxVertices(mGeometryShaderMaxVertices);
        }
        else if (mGeometryShaderMaxVertices != layoutQualifier.maxVertices)
        {
            error(typeQualifier.line, "max_vertices contradicts to the earlier declaration",
                  "layout");
            return false;
        }
    }

    return true;
}

bool TParseContext::parseTessControlShaderOutputLayoutQualifier(const TTypeQualifier &typeQualifier)
{
    ASSERT(typeQualifier.qualifier == EvqTessControlOut);

    const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier;

    if (layoutQualifier.vertices == 0)
    {
        error(typeQualifier.line, "No vertices specified", "layout");
        return false;
    }

    // Set mTessControlShaderOutputVertices if exists
    if (mTessControlShaderOutputVertices == 0)
    {
        mTessControlShaderOutputVertices = layoutQualifier.vertices;
        mIRBuilder.setTcsVertices(mTessControlShaderOutputVertices);

        // Size any implicitly sized arrays that have already been declared.
        sizeUnsizedArrayTypes(mTessControlShaderOutputVertices);
    }
    else
    {
        error(typeQualifier.line, "Duplicated vertices specified", "layout");
    }
    return true;
}

bool TParseContext::parseTessEvaluationShaderInputLayoutQualifier(
    const TTypeQualifier &typeQualifier)
{
    ASSERT(typeQualifier.qualifier == EvqTessEvaluationIn);

    const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier;

    // Set mTessEvaluationShaderInputPrimitiveType if exists
    if (layoutQualifier.tesPrimitiveType != EtetUndefined)
    {
        if (mTessEvaluationShaderInputPrimitiveType == EtetUndefined)
        {
            mTessEvaluationShaderInputPrimitiveType = layoutQualifier.tesPrimitiveType;
            mIRBuilder.setTesPrimitive(mTessEvaluationShaderInputPrimitiveType);
        }
        else
        {
            error(typeQualifier.line, "Duplicated primitive type declaration", "layout");
        }
    }
    // Set mTessEvaluationShaderVertexSpacingType if exists
    if (layoutQualifier.tesVertexSpacingType != EtetUndefined)
    {
        if (mTessEvaluationShaderInputVertexSpacingType == EtetUndefined)
        {
            mTessEvaluationShaderInputVertexSpacingType = layoutQualifier.tesVertexSpacingType;
            mIRBuilder.setTesVertexSpacing(mTessEvaluationShaderInputVertexSpacingType);
        }
        else
        {
            error(typeQualifier.line, "Duplicated vertex spacing declaration", "layout");
        }
    }
    // Set mTessEvaluationShaderInputOrderingType if exists
    if (layoutQualifier.tesOrderingType != EtetUndefined)
    {
        if (mTessEvaluationShaderInputOrderingType == EtetUndefined)
        {
            mTessEvaluationShaderInputOrderingType = layoutQualifier.tesOrderingType;
            mIRBuilder.setTesOrdering(mTessEvaluationShaderInputOrderingType);
        }
        else
        {
            error(typeQualifier.line, "Duplicated ordering declaration", "layout");
        }
    }
    // Set mTessEvaluationShaderInputPointType if exists
    if (layoutQualifier.tesPointType != EtetUndefined)
    {
        if (mTessEvaluationShaderInputPointType == EtetUndefined)
        {
            mTessEvaluationShaderInputPointType = layoutQualifier.tesPointType;
            mIRBuilder.setTesPointMode(mTessEvaluationShaderInputPointType);
        }
        else
        {
            error(typeQualifier.line, "Duplicated point type declaration", "layout");
        }
    }

    return true;
}

void TParseContext::sizeUnsizedArrayTypes(uint32_t arraySize)
{
    while (!mDeferredArrayTypesToSize.empty())
    {
        TType *type = mDeferredArrayTypesToSize.back();

        // Pop the type out of |mDeferredArrayTypesToSize| to satisfy an ASSERT in |getTypeId| that
        // the type declaration is not deferred!
        mDeferredArrayTypesToSize.pop_back();

        type->sizeOutermostUnsizedArray(arraySize);
        type->setTypeId(getTypeId(*type));
    }

    for (const TVariable *variable : mDeferredArrayVariablesToSize)
    {
        declareIRVariable(variable, GeomTessArray::Sized);
    }
    mDeferredArrayVariablesToSize.clear();
}

void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder)
{
    TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
    const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;

    checkInvariantVariableQualifier(typeQualifier.invariant, typeQualifier.qualifier,
                                    typeQualifier.line);

    // It should never be the case, but some strange parser errors can send us here.
    if (layoutQualifier.isEmpty())
    {
        error(typeQualifier.line, "Error during layout qualifier parsing.", "?");
        return;
    }

    if (!layoutQualifier.isCombinationValid())
    {
        error(typeQualifier.line, "invalid layout qualifier combination", "layout");
        return;
    }

    checkIndexIsNotSpecified(typeQualifier.line, layoutQualifier.index);

    checkBindingIsNotSpecified(typeQualifier.line, layoutQualifier.binding);

    checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);

    checkInternalFormatIsNotSpecified(typeQualifier.line, layoutQualifier.imageInternalFormat);

    checkDepthIsNotSpecified(typeQualifier.line, layoutQualifier.depth);

    checkYuvIsNotSpecified(typeQualifier.line, layoutQualifier.yuv);

    checkOffsetIsNotSpecified(typeQualifier.line, layoutQualifier.offset);

    checkStd430IsForShaderStorageBlock(typeQualifier.line, layoutQualifier.blockStorage,
                                       typeQualifier.qualifier);

    checkAdvancedBlendEquationsNotSpecified(
        typeQualifier.line, layoutQualifier.advancedBlendEquations, typeQualifier.qualifier);

    if (typeQualifier.qualifier != EvqFragmentIn)
    {
        checkEarlyFragmentTestsIsNotSpecified(typeQualifier.line,
                                              layoutQualifier.earlyFragmentTests);
    }

    if (typeQualifier.qualifier == EvqComputeIn)
    {
        if (mComputeShaderLocalSizeDeclared &&
            !layoutQualifier.isLocalSizeEqual(mComputeShaderLocalSize))
        {
            error(typeQualifier.line, "Work group size does not match the previous declaration",
                  "layout");
            return;
        }

        if (mShaderVersion < 310)
        {
            error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
            return;
        }

        if (!layoutQualifier.localSize.isAnyValueSet())
        {
            error(typeQualifier.line, "No local work group size specified", "layout");
            return;
        }

        const TVariable *maxComputeWorkGroupSize = static_cast<const TVariable *>(
            symbolTable.findBuiltIn(ImmutableString("gl_MaxComputeWorkGroupSize"), mShaderVersion));

        const TConstantUnion *maxComputeWorkGroupSizeData =
            maxComputeWorkGroupSize->getConstPointer();

        for (size_t i = 0u; i < layoutQualifier.localSize.size(); ++i)
        {
            if (layoutQualifier.localSize[i] != -1)
            {
                mComputeShaderLocalSize[i]             = layoutQualifier.localSize[i];
                const int maxComputeWorkGroupSizeValue =
                    ANGLE_UNSAFE_TODO(maxComputeWorkGroupSizeData[i]).getIConst();
                if (mComputeShaderLocalSize[i] < 1 ||
                    mComputeShaderLocalSize[i] > maxComputeWorkGroupSizeValue)
                {
                    std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
                    reasonStream << "invalid value: Value must be at least 1 and no greater than "
                                 << maxComputeWorkGroupSizeValue;
                    const std::string &reason = reasonStream.str();

                    error(typeQualifier.line, reason.c_str(), getWorkGroupSizeString(i));
                    return;
                }
            }
        }

        mComputeShaderLocalSizeDeclared = true;
    }
    else if (typeQualifier.qualifier == EvqGeometryIn)
    {
        if (mShaderVersion < 310)
        {
            error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
            return;
        }

        if (!parseGeometryShaderInputLayoutQualifier(typeQualifier))
        {
            return;
        }
    }
    else if (typeQualifier.qualifier == EvqGeometryOut)
    {
        if (mShaderVersion < 310)
        {
            error(typeQualifier.line, "out type qualifier supported in GLSL ES 3.10 only",
                  "layout");
            return;
        }

        if (!parseGeometryShaderOutputLayoutQualifier(typeQualifier))
        {
            return;
        }
    }
    else if (anyMultiviewExtensionAvailable() && typeQualifier.qualifier == EvqVertexIn)
    {
        // This error is only specified in WebGL, but tightens unspecified behavior in the native
        // specification.
        if (mNumViews != -1 && layoutQualifier.numViews != mNumViews)
        {
            error(typeQualifier.line, "Number of views does not match the previous declaration",
                  "layout");
            return;
        }

        if (layoutQualifier.numViews == -1)
        {
            error(typeQualifier.line, "No num_views specified", "layout");
            return;
        }

        if (layoutQualifier.numViews > mResources.MaxViewsOVR)
        {
            error(typeQualifier.line, "num_views greater than the value of GL_MAX_VIEWS_OVR",
                  "layout");
            return;
        }

        mNumViews = layoutQualifier.numViews;
        mIRBuilder.setNumViews(mNumViews);
    }
    else if (typeQualifier.qualifier == EvqFragmentIn)
    {
        if (mShaderVersion < 310)
        {
            error(typeQualifier.line,
                  "in type qualifier without variable declaration supported in GLSL ES 3.10 and "
                  "after",
                  "layout");
            return;
        }

        if (!layoutQualifier.earlyFragmentTests)
        {
            error(typeQualifier.line,
                  "only early_fragment_tests is allowed as layout qualifier when not declaring a "
                  "variable",
                  "layout");
            return;
        }

        mEarlyFragmentTestsSpecified = true;
        mIRBuilder.setEarlyFragmentTests(mEarlyFragmentTestsSpecified);
    }
    else if (typeQualifier.qualifier == EvqFragmentOut)
    {
        if (mShaderVersion < 320 && !isExtensionEnabled(TExtension::KHR_blend_equation_advanced))
        {
            error(typeQualifier.line,
                  "out type qualifier without variable declaration is supported in GLSL ES 3.20,"
                  " or if GL_KHR_blend_equation_advanced is enabled",
                  "layout");
            return;
        }

        if (!layoutQualifier.advancedBlendEquations.any())
        {
            error(typeQualifier.line,
                  "only blend equations are allowed as layout qualifier when not declaring a "
                  "variable",
                  "layout");
            return;
        }

        errorIfPLSDeclared(typeQualifier.line, PLSIllegalOperations::EnableAdvancedBlendEquation);
        mAdvancedBlendEquations |= layoutQualifier.advancedBlendEquations;
    }
    else if (typeQualifier.qualifier == EvqTessControlOut)
    {
        if (mShaderVersion < 310)
        {
            error(typeQualifier.line, "out type qualifier supported in GLSL ES 3.10 and after",
                  "layout");
            return;
        }

        if (!parseTessControlShaderOutputLayoutQualifier(typeQualifier))
        {
            return;
        }
    }
    else if (typeQualifier.qualifier == EvqTessEvaluationIn)
    {
        if (mShaderVersion < 310)
        {
            error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 and after",
                  "layout");
            return;
        }

        if (!parseTessEvaluationShaderInputLayoutQualifier(typeQualifier))
        {
            return;
        }
    }
    else
    {
        if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, layoutQualifier))
        {
            return;
        }

        if (typeQualifier.qualifier != EvqUniform && typeQualifier.qualifier != EvqBuffer)
        {
            error(typeQualifier.line, "invalid qualifier: global layout can only be set for blocks",
                  getQualifierString(typeQualifier.qualifier));
            return;
        }

        if (mShaderVersion < 300)
        {
            error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and after",
                  "layout");
            return;
        }

        checkLocationIsNotSpecified(typeQualifier.line, layoutQualifier);

        if (layoutQualifier.matrixPacking != EmpUnspecified)
        {
            if (typeQualifier.qualifier == EvqUniform)
            {
                mDefaultUniformMatrixPacking = layoutQualifier.matrixPacking;
            }
            else if (typeQualifier.qualifier == EvqBuffer)
            {
                mDefaultBufferMatrixPacking = layoutQualifier.matrixPacking;
            }
        }

        if (layoutQualifier.blockStorage != EbsUnspecified)
        {
            if (typeQualifier.qualifier == EvqUniform)
            {
                mDefaultUniformBlockStorage = layoutQualifier.blockStorage;
            }
            else if (typeQualifier.qualifier == EvqBuffer)
            {
                mDefaultBufferBlockStorage = layoutQualifier.blockStorage;
            }
        }
    }
}

TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction(
    const TFunction &function,
    const TSourceLoc &location,
    bool insertParametersToSymbolTable)
{
    checkIsNotReserved(location, function.name());

    TIntermFunctionPrototype *prototype = new TIntermFunctionPrototype(&function);
    prototype->setLine(location);

    for (size_t i = 0; i < function.getParamCount(); i++)
    {
        const TVariable *param = function.getParam(i);

        // If the parameter has no name, it's not an error, just don't add it to symbol table (could
        // be used for unused args).
        if (param->symbolType() != SymbolType::Empty)
        {
            if (insertParametersToSymbolTable)
            {
                if (!symbolTable.declare(const_cast<TVariable *>(param)))
                {
                    error(location, "redefinition", param->name());
                }
            }
            // Unsized type of a named parameter should have already been checked and sanitized.
            ASSERT(!param->getType().isUnsizedArray());
        }
    }
    return prototype;
}

TIntermFunctionPrototype *TParseContext::addFunctionPrototypeDeclaration(
    const TFunction &parsedFunction,
    const TSourceLoc &location)
{
    // Note: function found from the symbol table could be the same as parsedFunction if this is the
    // first declaration. Either way the instance in the symbol table is used to track whether the
    // function is declared multiple times.
    bool hadPrototypeDeclaration = false;
    const TFunction *function    = symbolTable.markFunctionHasPrototypeDeclaration(
        parsedFunction.getMangledName(), &hadPrototypeDeclaration);

    if (hadPrototypeDeclaration && mShaderVersion == 100)
    {
        // ESSL 1.00.17 section 4.2.7.
        // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
        error(location, "duplicate function prototype declarations are not allowed", "function");
    }

    TIntermFunctionPrototype *prototype =
        createPrototypeNodeFromFunction(*function, location, false);

    symbolTable.pop();

    if (!symbolTable.atGlobalLevel())
    {
        // ESSL 3.00.4 section 4.2.4.
        error(location, "local function prototype declarations are not allowed", "function");
    }

    // Declare the function to the IR.  It's body is not yet specified.
    declareFunction(function, FunctionDeclaration::Prototype);
    return prototype;
}

TIntermFunctionDefinition *TParseContext::addFunctionDefinition(
    TIntermFunctionPrototype *functionPrototype,
    TIntermBlock *functionBody,
    const TSourceLoc &location)
{
    ASSERT(functionPrototype->getFunction() == mCurrentFunction);

    // Undo push at end of parseFunctionDefinitionHeader() below for ESSL1.00 case
    if (mFunctionBodyNewScope)
    {
        mFunctionBodyNewScope = false;
        symbolTable.pop();
    }

    // Check that non-void functions have at least one return statement.
    if (mCurrentFunction->getReturnType().getBasicType() != EbtVoid && !mFunctionReturnsValue)
    {
        error(location, "Function does not return a value", mCurrentFunction->name());
    }
    if (mCompileOptions.limitExpressionComplexity &&
        mCurrentFunction->getParamCount() >
            static_cast<unsigned int>(mResources.MaxFunctionParameters))
    {
        error(location, "Function has too many parameters", mCurrentFunction->name());
    }

    for (size_t paramIndex = 0; paramIndex < mCurrentFunction->getParamCount(); ++paramIndex)
    {
        const TVariable *param = mCurrentFunction->getParam(paramIndex);
        checkVariableSize(functionPrototype->getLine(), param->name(), &param->getType());
    }

    if (functionBody == nullptr)
    {
        functionBody = new TIntermBlock();
        functionBody->setLine(location);
    }
    TIntermFunctionDefinition *functionNode =
        new TIntermFunctionDefinition(functionPrototype, functionBody);
    functionNode->setLine(location);

    if (mDeclaringMain)
    {
        mMainFunction = mCurrentFunction;
    }
    mCurrentFunction = nullptr;

    mIRBuilder.endFunction();

    symbolTable.pop();
    return functionNode;
}

void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location,
                                                  const TFunction *function,
                                                  TIntermFunctionPrototype **prototypeOut)
{
    ASSERT(function);

    bool wasDefined = false;
    function        = symbolTable.setFunctionParameterNamesFromDefinition(function, &wasDefined);
    if (wasDefined)
    {
        error(location, "function already has a body", function->name());
    }

    // Remember the return type for later checking for return statements.
    mCurrentFunction      = function;
    mFunctionReturnsValue = false;
    // The function is about to be defined
    mDefinedFunctions.insert(function);

    *prototypeOut = createPrototypeNodeFromFunction(*function, location, true);
    ASSERT(mControlFlow.empty());

    // ESSL 1.00 spec allows for variable in function body to redefine parameter
    if (IsSpecWithFunctionBodyNewScope(mShaderSpec, mShaderVersion))
    {
        mFunctionBodyNewScope = true;
        symbolTable.push();
    }

    // If the function prototype hasn't been previously encountered, this is a new function that
    // should be declared to the IR first.
    declareFunction(function, FunctionDeclaration::Definition);
    mIRBuilder.beginFunction(mFunctionToId.at(function));
}

TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
{
    //
    // We don't know at this point whether this is a function definition or a prototype.
    // The definition production code will check for redefinitions.
    // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
    //

    for (size_t i = 0u; i < function->getParamCount(); ++i)
    {
        const TVariable *param = function->getParam(i);
        const TType &paramType = param->getType();

        checkPrecisionSpecified(location, paramType.getPrecision(), paramType.getBasicType());
    }

    if (getShaderVersion() >= 300)
    {
        if (symbolTable.isUnmangledBuiltInName(function->name(), getShaderVersion(),
                                               extensionBehavior()))
        {
            // With ESSL 3.00 and above, names of built-in functions cannot be redeclared as
            // functions. Therefore overloading or redefining builtin functions is an error.
            error(location, "Name of a built-in function cannot be redeclared as function",
                  function->name());
        }
    }
    else
    {
        // ESSL 1.00.17 section 4.2.6: built-ins can be overloaded but not redefined. We assume that
        // this applies to redeclarations as well.
        const TSymbol *builtIn =
            symbolTable.findBuiltIn(function->getMangledName(), getShaderVersion());
        if (builtIn)
        {
            error(location, "built-in functions cannot be redefined", function->name());
        }
    }

    // Return types and parameter qualifiers must match in all redeclarations, so those are checked
    // here.
    const TFunction *prevDec =
        static_cast<const TFunction *>(symbolTable.findGlobal(function->getMangledName()));
    if (prevDec)
    {
        if (prevDec->getReturnType() != function->getReturnType())
        {
            error(location, "function must have the same return type in all of its declarations",
                  function->getReturnType().getBasicString());
        }
        for (size_t i = 0; i < prevDec->getParamCount(); ++i)
        {
            if (prevDec->getParam(i)->getType().getQualifier() !=
                function->getParam(i)->getType().getQualifier())
            {
                error(location,
                      "function must have the same parameter qualifiers in all of its declarations",
                      function->getParam(i)->getType().getQualifierString());
            }
        }
    }

    // Check for previously declared variables using the same name.
    const TSymbol *prevSym   = symbolTable.find(function->name(), getShaderVersion());
    bool insertUnmangledName = true;
    if (prevSym)
    {
        if (!prevSym->isFunction())
        {
            error(location, "redefinition of a function", function->name());
        }
        insertUnmangledName = false;
    }
    // Parsing is at the inner scope level of the function's arguments and body statement at this
    // point, but declareUserDefinedFunction takes care of declaring the function at the global
    // scope.
    symbolTable.declareUserDefinedFunction(function, insertUnmangledName);

    // Raise error message if main function takes any parameters or return anything other than void
    if (function->isMain())
    {
        if (function->getParamCount() > 0)
        {
            error(location, "function cannot take any parameter(s)", "main");
        }
        if (function->getReturnType().getBasicType() != EbtVoid)
        {
            error(location, "main function cannot return a value",
                  function->getReturnType().getBasicString());
        }
    }

    mDeclaringMain         = function->isMain();
    mIsReturnVisitedInMain = false;

    //
    // If this is a redeclaration, it could also be a definition, in which case, we want to use the
    // variable names from this one, and not the one that's
    // being redeclared.  So, pass back up this declaration, not the one in the symbol table.
    //
    return function;
}

TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
                                              const ImmutableString &name,
                                              const TSourceLoc &location)
{
    if (type.qualifier != EvqGlobal && type.qualifier != EvqTemporary)
    {
        error(location, "no qualifiers allowed for function return",
              getQualifierString(type.qualifier));
    }
    if (!type.layoutQualifier.isEmpty())
    {
        error(location, "no qualifiers allowed for function return", "layout");
    }
    // make sure an opaque type is not involved as well...
    std::string reason(getBasicString(type.getBasicType()));
    reason += "s can't be function return values";
    checkIsNotOpaqueType(location, type.typeSpecifierNonArray, reason.c_str());
    if (mShaderVersion < 300)
    {
        // Array return values are forbidden, but there's also no valid syntax for declaring array
        // return values in ESSL 1.00.
        ASSERT(!type.isArray() || mDiagnostics->numErrors() > 0);

        if (type.isStructureContainingArrays())
        {
            // ESSL 1.00.17 section 6.1 Function Definitions
            TInfoSinkBase typeString;
            typeString << TType(type);
            error(location, "structures containing arrays can't be function return values",
                  typeString.c_str());
        }
    }

    // Add the function as a prototype after parsing it (we do not support recursion)
    return new TFunction(&symbolTable, name, SymbolType::UserDefined, new TType(type), false);
}

TFunctionLookup *TParseContext::addNonConstructorFunc(const ImmutableString &name,
                                                      const TSymbol *symbol)
{
    return TFunctionLookup::CreateFunctionCall(name, symbol);
}

TFunctionLookup *TParseContext::addConstructorFunc(const TPublicType &publicType)
{
    if (mShaderVersion < 300 && publicType.isArray())
    {
        error(publicType.getLine(), "array constructor supported in GLSL ES 3.00 and above only",
              "[]");
    }
    if (publicType.isStructSpecifierForValidation())
    {
        error(publicType.getLine(), "constructor can't be a structure definition",
              getBasicString(publicType.getBasicType()));
    }

    TType *type = new TType(publicType);
    if (!type->canBeConstructed())
    {
        error(publicType.getLine(), "cannot construct this type",
              getBasicString(publicType.getBasicType()));
        type->setBasicType(EbtFloat);
    }
    return TFunctionLookup::CreateConstructor(type);
}

void TParseContext::checkIsNotUnsizedArray(const TSourceLoc &line,
                                           const char *errorMessage,
                                           const ImmutableString &token,
                                           TType *arrayType)
{
    if (arrayType->isUnsizedArray())
    {
        error(line, errorMessage, token);
        arrayType->sizeUnsizedArrays(angle::Span<const unsigned int>());
    }
}

TParameter TParseContext::parseParameterDeclarator(const TPublicType &type,
                                                   const ImmutableString &name,
                                                   const TSourceLoc &nameLoc)
{
    if (!name.empty())
    {
        if (type.getBasicType() == EbtVoid)
        {
            error(nameLoc, "illegal use of type 'void'", name);
        }
    }
    if (type.isStructSpecifierForValidation())
    {
        // ESSL 3.00.6 section 12.10.
        error(nameLoc, "Function parameter type cannot be a structure definition", name);
    }
    checkIsNotReserved(nameLoc, name);
    TParameter param{name.data(), type};
    if (param.type.isUnsizedArray())
    {
        error(nameLoc, "function parameter array must specify a size", name);
        param.type.sizeUnsizedArrays();
    }
    return param;
}

TParameter TParseContext::parseParameterArrayDeclarator(const TPublicType &elementType,
                                                        const ImmutableString &name,
                                                        const TSourceLoc &nameLoc,
                                                        TVector<unsigned int> *arraySizes,
                                                        const TSourceLoc &arrayLoc)
{
    checkArrayElementIsNotArray(arrayLoc, elementType);
    TPublicType arrayType{elementType};
    arrayType.makeArrays(arraySizes);
    return parseParameterDeclarator(arrayType, name, nameLoc);
}

bool TParseContext::checkUnsizedArrayConstructorArgumentDimensionality(
    const TIntermSequence &arguments,
    TType type,
    const TSourceLoc &line)
{
    if (arguments.empty())
    {
        error(line, "implicitly sized array constructor must have at least one argument", "[]");
        return false;
    }
    for (TIntermNode *arg : arguments)
    {
        const TIntermTyped *element = arg->getAsTyped();
        ASSERT(element);
        if (element->getType().isUnsizedArray())
        {
            error(line, "constructing from an unsized array", "constructor");
            return false;
        }
        size_t dimensionalityFromElement = element->getType().getNumArraySizes() + 1u;
        if (dimensionalityFromElement > type.getNumArraySizes())
        {
            error(line, "constructing from a non-dereferenced array", "constructor");
            return false;
        }
        else if (dimensionalityFromElement < type.getNumArraySizes())
        {
            if (dimensionalityFromElement == 1u)
            {
                error(line, "implicitly sized array of arrays constructor argument is not an array",
                      "constructor");
            }
            else
            {
                error(line,
                      "implicitly sized array of arrays constructor argument dimensionality is too "
                      "low",
                      "constructor");
            }
            return false;
        }
    }
    return true;
}

// This function is used to test for the correctness of the parameters passed to various constructor
// functions and also convert them to the right datatype if it is allowed and required.
//
// Returns a node to add to the tree regardless of if an error was generated or not.
//
TIntermTyped *TParseContext::addConstructor(TFunctionLookup *fnCall, const TSourceLoc &line)
{
    TType type = fnCall->constructorType();
    checkVariableSize(line, ImmutableString(""), &type);

    TIntermSequence &arguments = fnCall->arguments();
    if (type.isUnsizedArray())
    {
        if (!checkUnsizedArrayConstructorArgumentDimensionality(arguments, type, line))
        {
            type.sizeUnsizedArrays(angle::Span<const unsigned int>());
            return CreateZeroNode(type);
        }
        TIntermTyped *firstElement = arguments.at(0)->getAsTyped();
        ASSERT(firstElement);
        if (type.getOutermostArraySize() == 0u)
        {
            type.sizeOutermostUnsizedArray(static_cast<unsigned int>(arguments.size()));
        }
        for (size_t i = 0; i < firstElement->getType().getNumArraySizes(); ++i)
        {
            if (type.getArraySizes()[i] == 0u)
            {
                type.setArraySize(i, firstElement->getType().getArraySizes()[i]);
            }
        }
        ASSERT(!type.isUnsizedArray());
    }

    if (!checkConstructorArguments(line, arguments, type))
    {
        return CreateZeroNode(type);
    }

    mIRBuilder.construct(getTypeId(type), arguments.size());

    TIntermAggregate *constructorNode = TIntermAggregate::CreateConstructor(type, &arguments);
    constructorNode->setLine(line);

    return constructorNode->fold(mDiagnostics);
}

//
// Interface/uniform blocks
TIntermDeclaration *TParseContext::addInterfaceBlock(
    const TTypeQualifierBuilder &typeQualifierBuilder,
    const TSourceLoc &nameLine,
    const ImmutableString &blockName,
    TFieldList *fieldList,
    const ImmutableString &instanceName,
    const TSourceLoc &instanceLine,
    const TVector<unsigned int> *arraySizes,
    const TSourceLoc &arraySizesLine)
{
    checkDoesNotHaveTooManyFields(blockName, fieldList, nameLine);

    // Ensure there are no duplicate field names
    checkDoesNotHaveDuplicateFieldNames(fieldList, nameLine);

    const bool isGLPerVertex = blockName == "gl_PerVertex";
    // gl_PerVertex is allowed to be redefined and therefore not reserved
    if (!isGLPerVertex)
    {
        checkIsNotReserved(nameLine, blockName);
    }

    TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);

    const bool isUniformOrBuffer =
        typeQualifier.qualifier == EvqUniform || typeQualifier.qualifier == EvqBuffer;
    const bool isShaderIoBlock = IsShaderIoBlock(typeQualifier.qualifier);

    if (mShaderVersion < 310 && typeQualifier.qualifier != EvqUniform)
    {
        error(typeQualifier.line,
              "invalid qualifier: interface blocks must be uniform in version lower than GLSL ES "
              "3.10",
              getQualifierString(typeQualifier.qualifier));
    }
    else if (typeQualifier.qualifier == EvqPatchOut)
    {
        if ((!isExtensionEnabled(TExtension::EXT_tessellation_shader) &&
             !isExtensionEnabled(TExtension::OES_tessellation_shader) && mShaderVersion < 320) ||
            mShaderType != GL_TESS_CONTROL_SHADER)
        {
            error(typeQualifier.line,
                  "invalid qualifier: 'patch out' requires a tessellation control shader",
                  getQualifierString(typeQualifier.qualifier));
        }
    }
    else if (typeQualifier.qualifier == EvqPatchIn)
    {
        if ((!isExtensionEnabled(TExtension::EXT_tessellation_shader) &&
             !isExtensionEnabled(TExtension::OES_tessellation_shader) && mShaderVersion < 320) ||
            mShaderType != GL_TESS_EVALUATION_SHADER)
        {
            error(typeQualifier.line,
                  "invalid qualifier: 'patch in' requires a tessellation evaluation shader",
                  getQualifierString(typeQualifier.qualifier));
        }
    }
    else if (typeQualifier.qualifier != EvqUniform && typeQualifier.qualifier != EvqBuffer)
    {
        if (isShaderIoBlock)
        {
            if (!isExtensionEnabled(TExtension::OES_shader_io_blocks) &&
                !isExtensionEnabled(TExtension::EXT_shader_io_blocks) &&
                !isExtensionEnabled(TExtension::OES_geometry_shader) &&
                !isExtensionEnabled(TExtension::EXT_geometry_shader) && mShaderVersion < 320)
            {
                error(typeQualifier.line,
                      "invalid qualifier: shader IO blocks need shader io block extension",
                      getQualifierString(typeQualifier.qualifier));
            }

            // Both inputs and outputs of tessellation control shaders must be arrays.
            // For tessellation evaluation shaders, only inputs must necessarily be arrays.
            // Inputs of geometry shaders must be arrays too.
            const bool isTCS = mShaderType == GL_TESS_CONTROL_SHADER;
            const bool isTESIn =
                mShaderType == GL_TESS_EVALUATION_SHADER && IsShaderIn(typeQualifier.qualifier);
            const bool isGSIn =
                mShaderType == GL_GEOMETRY_SHADER && IsShaderIn(typeQualifier.qualifier);
            if (arraySizes == nullptr && (isTCS || isTESIn || isGSIn))
            {
                error(typeQualifier.line, "type must be an array", blockName);
            }
        }
        else
        {
            error(typeQualifier.line,
                  "invalid qualifier: interface blocks must be uniform or buffer",
                  getQualifierString(typeQualifier.qualifier));
        }
    }

    if (typeQualifier.invariant)
    {
        error(typeQualifier.line, "invalid qualifier on interface block", "invariant");
    }

    if (typeQualifier.qualifier != EvqBuffer)
    {
        checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
    }

    // Verify array sizes
    if (arraySizes)
    {
        if (isUniformOrBuffer)
        {
            if (arraySizes->size() == 0)
            {
                error(arraySizesLine, "unsized arrays are not allowed with interface blocks", "");
            }
            if (arraySizes->size() > 1)
            {
                error(arraySizesLine, "array of arrays are not allowed with interface blocks", "");
            }
        }
        else if (isShaderIoBlock)
        {
            size_t arrayDimensions = arraySizes->size();

            // Geometry shader inputs have a level arrayness that must be ignored.
            if (mShaderType == GL_GEOMETRY_SHADER_EXT && IsVaryingIn(typeQualifier.qualifier))
            {
                ASSERT(arrayDimensions > 0);
                --arrayDimensions;

                // Validate that the array size of input matches the geometry layout
                // declaration, if not automatic (specified as []).
                const unsigned int geometryDim = arraySizes->back();
                if (geometryDim > 0 && geometryDim != mGeometryInputArraySize)
                {
                    error(arraySizesLine,
                          "geometry shader input block array size inconsistent "
                          "with primitive",
                          "");
                }
            }

            if (arrayDimensions > 1)
            {
                error(arraySizesLine, "array of arrays are not allowed with I/O blocks", "");
            }
        }
    }
    else if (isShaderIoBlock && mShaderType == GL_GEOMETRY_SHADER_EXT &&
             IsVaryingIn(typeQualifier.qualifier))
    {
        error(arraySizesLine, "geometry shader input blocks must be an array", "");
    }

    // Validate max uniform block limits
    if (typeQualifier.qualifier == EvqUniform)
    {
        unsigned int blockCount =
            arraySizes == nullptr || arraySizes->empty() ? 1 : (*arraySizes)[0];
        if (mNumUniformBlocks + blockCount > mMaxUniformBlocks)
        {
            error(arraySizesLine,
                  "uniform block count greater than per stage maximum uniform blocks", "");
        }
        else
        {
            mNumUniformBlocks += blockCount;
        }
    }

    checkIndexIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.index);

    if (mShaderVersion < 310)
    {
        checkBindingIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.binding);
    }
    else
    {
        unsigned int arraySize =
            arraySizes == nullptr || arraySizes->empty() ? 0 : (*arraySizes)[0];
        checkBlockBindingIsValid(typeQualifier.line, typeQualifier.qualifier,
                                 typeQualifier.layoutQualifier.binding, arraySize);
    }

    checkDepthIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.depth);
    checkYuvIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.yuv);
    checkEarlyFragmentTestsIsNotSpecified(typeQualifier.line,
                                          typeQualifier.layoutQualifier.earlyFragmentTests);
    checkNoncoherentIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.noncoherent);

    TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
    if (!IsShaderIoBlock(typeQualifier.qualifier) && typeQualifier.qualifier != EvqPatchIn &&
        typeQualifier.qualifier != EvqPatchOut)
    {
        checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier);
    }
    checkStd430IsForShaderStorageBlock(typeQualifier.line, blockLayoutQualifier.blockStorage,
                                       typeQualifier.qualifier);

    if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
    {
        if (typeQualifier.qualifier == EvqUniform)
        {
            blockLayoutQualifier.matrixPacking = mDefaultUniformMatrixPacking;
        }
        else if (typeQualifier.qualifier == EvqBuffer)
        {
            blockLayoutQualifier.matrixPacking = mDefaultBufferMatrixPacking;
        }
    }

    if (blockLayoutQualifier.blockStorage == EbsUnspecified)
    {
        if (typeQualifier.qualifier == EvqUniform)
        {
            blockLayoutQualifier.blockStorage = mDefaultUniformBlockStorage;
        }
        else if (typeQualifier.qualifier == EvqBuffer)
        {
            blockLayoutQualifier.blockStorage = mDefaultBufferBlockStorage;
        }
    }

    checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier);

    checkInternalFormatIsNotSpecified(nameLine, blockLayoutQualifier.imageInternalFormat);

    // check for sampler types and apply layout qualifiers
    for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
    {
        TField *field    = (*fieldList)[memberIndex];
        TType *fieldType = field->type();
        if (ContainsOpaque<IsOpaqueFunc>(*fieldType))
        {
            error(field->line(), "Opaque types are not allowed in interface blocks", blockName);
        }

        const TQualifier qualifier = fieldType->getQualifier();
        switch (qualifier)
        {
            case EvqGlobal:
                break;
            case EvqUniform:
                if (typeQualifier.qualifier == EvqBuffer)
                {
                    error(field->line(), "invalid qualifier on shader storage block member",
                          getQualifierString(qualifier));
                }
                break;
            case EvqBuffer:
                if (typeQualifier.qualifier == EvqUniform)
                {
                    error(field->line(), "invalid qualifier on uniform block member",
                          getQualifierString(qualifier));
                }
                break;
            // a member variable in io block may have different interpolation.
            case EvqSmoothIn:
            case EvqSmoothOut:
            case EvqFlatIn:
            case EvqFlatOut:
            case EvqNoPerspectiveIn:
            case EvqNoPerspectiveOut:
            case EvqCentroidIn:
            case EvqCentroidOut:
            case EvqSampleIn:
            case EvqSampleOut:
            case EvqNoPerspectiveCentroidIn:
            case EvqNoPerspectiveCentroidOut:
            case EvqNoPerspectiveSampleIn:
            case EvqNoPerspectiveSampleOut:
                break;
            // a member variable can have an incomplete qualifier because shader io block has either
            // in or out.
            case EvqSmooth:
            case EvqFlat:
            case EvqNoPerspective:
            case EvqCentroid:
            case EvqSample:
            case EvqNoPerspectiveCentroid:
            case EvqNoPerspectiveSample:
            case EvqGeometryIn:
            case EvqGeometryOut:
                if (!IsShaderIoBlock(typeQualifier.qualifier) &&
                    typeQualifier.qualifier != EvqPatchIn &&
                    typeQualifier.qualifier != EvqPatchOut &&
                    typeQualifier.qualifier != EvqGeometryIn &&
                    typeQualifier.qualifier != EvqGeometryOut)
                {
                    error(field->line(), "invalid qualifier on interface block member",
                          getQualifierString(qualifier));
                }
                break;
            default:
                error(field->line(), "invalid qualifier on interface block member",
                      getQualifierString(qualifier));
                break;
        }

        // On interface block members, invariant is only applicable to output I/O blocks.
        const bool isOutputShaderIoBlock = isShaderIoBlock && IsShaderOut(typeQualifier.qualifier);
        if (fieldType->isInvariant() && !isOutputShaderIoBlock)
        {
            error(field->line(), "invalid qualifier on interface block member", "invariant");
        }
        // Set invariant on output I/O blocks if invariant(all) is globally specified
        if (isOutputShaderIoBlock && mDirectiveHandler.pragma().stdgl.invariantAll &&
            (mCompileOptions.flattenPragmaSTDGLInvariantAll || mCompileOptions.useIR))
        {
            fieldType->setInvariant(true);
        }

        // check layout qualifiers
        TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
        checkIndexIsNotSpecified(field->line(), fieldLayoutQualifier.index);
        checkBindingIsNotSpecified(field->line(), fieldLayoutQualifier.binding);

        if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
        {
            error(field->line(), "invalid layout qualifier: cannot be used here",
                  getBlockStorageString(fieldLayoutQualifier.blockStorage));
        }

        if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
        {
            fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
        }
        else if (!fieldType->isMatrix() && fieldType->getBasicType() != EbtStruct)
        {
            warning(field->line(),
                    "extraneous layout qualifier: only has an effect on matrix types",
                    getMatrixPackingString(fieldLayoutQualifier.matrixPacking));
        }

        fieldType->setLayoutQualifier(fieldLayoutQualifier);

        if (mShaderVersion < 310 || memberIndex != fieldList->size() - 1u ||
            typeQualifier.qualifier != EvqBuffer)
        {
            // ESSL 3.10 spec section 4.1.9 allows for runtime-sized arrays.
            checkIsNotUnsizedArray(field->line(),
                                   "array members of interface blocks must specify a size",
                                   field->name(), field->type());
        }

        if (typeQualifier.qualifier == EvqBuffer)
        {
            // set memory qualifiers
            // GLSL ES 3.10 session 4.9 [Memory Access Qualifiers]. When a block declaration is
            // qualified with a memory qualifier, it is as if all of its members were declared with
            // the same memory qualifier.
            const TMemoryQualifier &blockMemoryQualifier = typeQualifier.memoryQualifier;
            TMemoryQualifier fieldMemoryQualifier        = fieldType->getMemoryQualifier();
            fieldMemoryQualifier.readonly |= blockMemoryQualifier.readonly;
            fieldMemoryQualifier.writeonly |= blockMemoryQualifier.writeonly;
            fieldMemoryQualifier.coherent |= blockMemoryQualifier.coherent;
            fieldMemoryQualifier.restrictQualifier |= blockMemoryQualifier.restrictQualifier;
            fieldMemoryQualifier.volatileQualifier |= blockMemoryQualifier.volatileQualifier;
            // TODO(jiajia.qin@intel.com): Decide whether if readonly and writeonly buffer variable
            // is legal. See bug https://github.com/KhronosGroup/OpenGL-API/issues/7
            fieldType->setMemoryQualifier(fieldMemoryQualifier);
        }

        // For per-vertex members, apply the appropriate built-in qualifiers to the members.
        if (isGLPerVertex)
        {
            if (field->name() == "gl_Position")
            {
                fieldType->setQualifier(EvqPosition);
            }
            if (field->name() == "gl_PointSize")
            {
                fieldType->setQualifier(EvqPointSize);
            }
            if (field->name() == "gl_ClipDistance")
            {
                fieldType->setQualifier(EvqClipDistance);
            }
            if (field->name() == "gl_CullDistance")
            {
                fieldType->setQualifier(EvqCullDistance);
            }
        }
    }

    SymbolType instanceSymbolType = SymbolType::UserDefined;
    if (isGLPerVertex)
    {
        // Mark gl_PerVertex as built-in if usage is not erroneous.  If it is, there will be failure
        // elsewhere that validates gl_PerVertex cannot be used when not a built-in.
        if (IsVaryingOut(typeQualifier.qualifier) && mShaderType != GL_FRAGMENT_SHADER &&
            mShaderType != GL_COMPUTE_SHADER)
        {
            instanceSymbolType      = SymbolType::BuiltIn;
            typeQualifier.qualifier = EvqPerVertexOut;
        }
        else if (IsVaryingIn(typeQualifier.qualifier) && mShaderType != GL_VERTEX_SHADER &&
                 mShaderType != GL_FRAGMENT_SHADER && mShaderType != GL_COMPUTE_SHADER)
        {
            instanceSymbolType      = SymbolType::BuiltIn;
            typeQualifier.qualifier = EvqPerVertexIn;
        }
    }
    TInterfaceBlock *interfaceBlock = new TInterfaceBlock(&symbolTable, blockName, fieldList,
                                                          blockLayoutQualifier, instanceSymbolType);
    if (!symbolTable.declare(interfaceBlock) && isUniformOrBuffer)
    {
        error(nameLine, "redefinition of an interface block name", blockName);
    }

    GeomTessArray sized = GeomTessArray::Sized;
    TType *interfaceBlockType =
        new TType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier);
    if (arraySizes)
    {
        interfaceBlockType->makeArrays(*arraySizes);
        checkDeclarationIsValidArraySize(instanceLine, instanceName, interfaceBlockType);
    }
    checkGeometryShaderInputAndSetArraySize(instanceLine, instanceName, interfaceBlockType, &sized);
    checkTessellationShaderUnsizedArraysAndSetSize(instanceLine, instanceName, interfaceBlockType,
                                                   &sized);

    // If this is gl_PerVertex, make sure the instance name is as expected.
    if (interfaceBlockType->getQualifier() == EvqPerVertexOut)
    {
        switch (mShaderType)
        {
            case GL_VERTEX_SHADER:
            case GL_TESS_EVALUATION_SHADER_EXT:
            case GL_GEOMETRY_SHADER_EXT:
                if (!instanceName.empty())
                {
                    error(instanceLine,
                          "out gl_PerVertex instance name must be empty in this shader",
                          instanceName);
                    instanceSymbolType = SymbolType::UserDefined;
                }
                break;
            case GL_TESS_CONTROL_SHADER_EXT:
                if (instanceName != "gl_out")
                {
                    error(instanceLine,
                          "out gl_PerVertex instance name must be gl_out in this shader",
                          instanceName);
                    instanceSymbolType = SymbolType::UserDefined;
                }
                break;
            default:
                UNREACHABLE();
                break;
        }
    }
    else if (interfaceBlockType->getQualifier() == EvqPerVertexIn)
    {
        if (instanceName != "gl_in")
        {
            error(instanceLine, "in gl_PerVertex instance name must be gl_in", instanceName);
            instanceSymbolType = SymbolType::UserDefined;
        }
    }

    if (sized == GeomTessArray::Sized)
    {
        interfaceBlockType->setTypeId(getTypeId(*interfaceBlockType));
    }

    // The instance variable gets created to refer to the interface block type from the AST
    // regardless of if there's an instance name. It's created as an empty symbol if there is no
    // instance name.
    TVariable *instanceVariable =
        new TVariable(&symbolTable, instanceName, interfaceBlockType,
                      instanceName.empty() ? SymbolType::Empty : instanceSymbolType);

    checkVariableSize(nameLine, blockName, interfaceBlockType);
    checkVariableLocations(nameLine, instanceVariable);
    declareIRVariable(instanceVariable, sized);

    if (instanceVariable->symbolType() == SymbolType::Empty)
    {
        // Cannot have an array variable that is yet to be sized but which also has no name (because
        // there is no way to specify arrayness with [] without a name).
        ASSERT(sized == GeomTessArray::Sized);
        const ir::VariableId instanceId = mVariableToId.at(instanceVariable).id;

        // define symbols for the members of the interface block
        for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
        {
            TField *field    = (*fieldList)[memberIndex];
            TType *fieldType = new TType(*field->type());

            // set parent pointer of the field variable
            fieldType->setInterfaceBlockField(interfaceBlock, memberIndex);

            fieldType->setQualifier(typeQualifier.qualifier);

            SymbolType symbolType = SymbolType::UserDefined;
            if (field->name() == "gl_Position" || field->name() == "gl_PointSize" ||
                field->name() == "gl_ClipDistance" || field->name() == "gl_CullDistance")
            {
                // These builtins can be redefined only when used within a redefined gl_PerVertex
                // block
                if (interfaceBlockType->getQualifier() != EvqPerVertexIn &&
                    interfaceBlockType->getQualifier() != EvqPerVertexOut)
                {
                    error(field->line(), "redefinition in an invalid interface block",
                          field->name());
                }
                symbolType = SymbolType::BuiltIn;
            }
            TVariable *fieldVariable =
                new TVariable(&symbolTable, field->name(), fieldType, symbolType);
            if (!symbolTable.declare(fieldVariable))
            {
                error(field->line(), "redefinition of an interface block member name",
                      field->name());
            }

            // Don't declare variables for fields of nameless interface blocks in the IR, just
            // remember to implicitly index the instance variable when referenced.
            mVariableToId[fieldVariable] =
                VariableToIdInfo{instanceId, static_cast<uint32_t>(memberIndex)};
        }
    }
    else
    {
        // gl_in and gl_out are allowed to be redeclared
        bool isGlIn =
            interfaceBlockType->getQualifier() == EvqPerVertexIn && instanceName == "gl_in";
        bool isGlOut = interfaceBlockType->getQualifier() == EvqPerVertexOut &&
                       instanceName == "gl_out" && mShaderType == GL_TESS_CONTROL_SHADER_EXT;

        if (!isGlIn && !isGlOut)
        {
            checkIsNotReserved(instanceLine, instanceName);
        }
        else if (isGlIn)
        {
            symbolTable.onGlInVariableRedeclaration(instanceVariable);
        }

        // add a symbol for this interface block
        if (!symbolTable.declare(instanceVariable))
        {
            error(instanceLine, "redefinition of an interface block instance name", instanceName);
        }
    }

    TIntermSymbol *blockSymbol = new TIntermSymbol(instanceVariable);
    blockSymbol->setLine(typeQualifier.line);
    TIntermDeclaration *declaration = new TIntermDeclaration();
    declaration->appendDeclarator(blockSymbol);
    declaration->setLine(nameLine);

    exitStructDeclaration();
    return declaration;
}

void TParseContext::enterStructDeclaration(const TSourceLoc &line,
                                           const ImmutableString &identifier)
{
    ++mStructNestingLevel;

    // Embedded structure definitions are not supported per GLSL ES spec.
    // ESSL 1.00.17 section 10.9. ESSL 3.00.6 section 12.11.
    if (mStructNestingLevel > 1)
    {
        error(line, "Embedded struct definitions are not allowed", "struct");
    }
}

void TParseContext::exitStructDeclaration()
{
    --mStructNestingLevel;
}

void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field)
{
    if (!sh::IsWebGLBasedSpec(mShaderSpec))
    {
        return;
    }

    if (field.type()->getBasicType() != EbtStruct)
    {
        return;
    }

    // We're already inside a structure definition at this point, so add
    // one to the field's struct nesting.
    if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
    {
        std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
        if (field.type()->getStruct()->symbolType() == SymbolType::Empty)
        {
            // This may happen in case there are nested struct definitions. While they are also
            // invalid GLSL, they don't cause a syntax error.
            reasonStream << "Struct nesting";
        }
        else
        {
            reasonStream << "Reference of struct type " << field.type()->getStruct()->name();
        }
        reasonStream << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
        std::string reason = reasonStream.str();
        error(line, reason.c_str(), field.name());
        return;
    }
}

//
// Parse an array index expression
//
TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
                                                const TSourceLoc &location,
                                                TIntermTyped *indexExpression)
{
    if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
    {
        if (baseExpression->getAsSymbolNode())
        {
            error(location, " left of '[' is not of type array, matrix, or vector ",
                  baseExpression->getAsSymbolNode()->getName());
        }
        else
        {
            error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
        }

        return CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
    }

    switch (baseExpression->getQualifier())
    {
        case EvqPerVertexIn:
            if (mGeometryShaderInputPrimitiveType == EptUndefined &&
                mShaderType == GL_GEOMETRY_SHADER_EXT)
            {
                error(location, "missing input primitive declaration before indexing gl_in.", "[");
                return CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
            }
            break;
        case EvqClipDistance:
            MarkClipCullIndex(location, indexExpression, &mClipDistanceInfo);
            break;
        case EvqCullDistance:
            MarkClipCullIndex(location, indexExpression, &mCullDistanceInfo);
            break;
        default:
            break;
    }

    TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();

    // ES3.2 or ES3.1's EXT_gpu_shader5 allow dynamically uniform expressions to be used as indices
    // of opaque types (samplers and atomic counters) as well as UBOs, but not SSBOs and images.
    bool allowUniformIndices = mShaderVersion >= 320 ||
                               isExtensionEnabled(TExtension::EXT_gpu_shader5) ||
                               isExtensionEnabled(TExtension::OES_gpu_shader5);

    // ANGLE should be able to fold any constant expressions resulting in an integer - but to be
    // safe we don't treat "EvqConst" that's evaluated according to the spec as being sufficient
    // for constness. Some interpretations of the spec have allowed constant expressions with side
    // effects - like array length() method on a non-constant array.
    if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr)
    {
        if (baseExpression->isInterfaceBlock())
        {
            switch (baseExpression->getQualifier())
            {
                case EvqPerVertexIn:
                    break;
                case EvqUniform:
                    if (!allowUniformIndices)
                    {
                        error(location,
                              "array indexes for uniform block arrays must be constant integral "
                              "expressions",
                              "[");
                    }
                    break;
                case EvqBuffer:
                    error(location,
                          "array indexes for shader storage block arrays must be constant integral "
                          "expressions",
                          "[");
                    break;
                default:
                    // It's ok for shader I/O blocks to be dynamically indexed
                    if (!IsShaderIoBlock(baseExpression->getQualifier()) &&
                        baseExpression->getQualifier() != EvqPatchIn &&
                        baseExpression->getQualifier() != EvqPatchOut)
                    {
                        // We can reach here only in error cases.
                        ASSERT(mDiagnostics->numErrors() > 0);
                    }
                    break;
            }
        }
        else if (baseExpression->getQualifier() == EvqFragmentOut ||
                 baseExpression->getQualifier() == EvqFragmentInOut)
        {
            error(location,
                  "array indexes for fragment outputs must be constant integral expressions", "[");
        }
        else if (baseExpression->getQualifier() == EvqLastFragData)
        {
            error(location,
                  "array indexes for gl_LastFragData must be constant integral expressions", "[");
        }
        else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData)
        {
            error(location, "array index for gl_FragData must be constant zero", "[");
        }
        else if (mShaderSpec == SH_WEBGL2_SPEC &&
                 baseExpression->getQualifier() == EvqSecondaryFragDataEXT)
        {
            error(location, "array index for gl_SecondaryFragDataEXT must be constant zero", "[");
        }
        else if (baseExpression->isArray())
        {
            TBasicType elementType = baseExpression->getType().getBasicType();

            // Note: In Section 12.30 of the ESSL 3.00 spec on p143-144:
            //
            //   Indexing of arrays of samplers by constant-index-expressions is
            //   supported in GLSL ES 1.00. A constant-index-expression is an
            //   expression formed from constant-expressions and certain loop indices,
            //   defined for a subset of loop constructs. Should this functionality be
            //   included in GLSL ES 3.00?
            //
            //   RESOLUTION: No. Arrays of samplers may only be indexed by constant-
            //   integral-expressions.
            if (IsSampler(elementType) && !allowUniformIndices && mShaderVersion > 100)
            {
                error(location, "array index for samplers must be constant integral expressions",
                      "[");
            }
            else if (IsImage(elementType))
            {
                error(location,
                      "array indexes for image arrays must be constant integral expressions", "[");
            }
        }
    }

    int index                   = 0;
    bool outOfRangeIndexIsError = false;

    // If the index is using the comma operator, descend to the right-most value, see if that's a
    // constant.  This is used for validating the index only, we can't constant fold the expression
    // due to the left-hand-side of the comma.
    TIntermTyped *commaRHS = indexExpression;
    while (true)
    {
        TIntermConstantUnion *constant = commaRHS->getAsConstantUnion();
        if (constant)
        {
            // If an out-of-range index is not qualified as constant, the behavior in the spec is
            // undefined. This applies even if ANGLE has been able to constant fold it (ANGLE may
            // constant fold expressions that are not constant expressions). The most compatible way
            // to handle this case is to report a warning instead of an error and force the index to
            // be in the correct range.
            outOfRangeIndexIsError = commaRHS->getQualifier() == EvqConst;
            index                  = 0;
            if (constant->getBasicType() == EbtInt)
            {
                index = constant->getIConst(0);
            }
            else if (constant->getBasicType() == EbtUInt)
            {
                index = static_cast<int>(constant->getUConst(0));
            }

            if (index < 0)
            {
                outOfRangeError(outOfRangeIndexIsError, location, "index expression is negative",
                                "[]");
            }
            break;
        }

        TIntermBinary *asBinary = commaRHS->getAsBinaryNode();
        if (asBinary == nullptr || asBinary->getOp() != EOpComma)
        {
            break;
        }
        commaRHS = asBinary->getRight();
    }

    if (indexConstantUnion)
    {
        int safeIndex = -1;
        if (index < 0)
        {
            safeIndex = 0;
        }

        if (!baseExpression->getType().isUnsizedArray())
        {
            if (baseExpression->isArray() && baseExpression->getQualifier() == EvqFragData)
            {
                mMaxFragDataArrayIndexUsed = std::max(mMaxFragDataArrayIndexUsed, index);
                if (index > 0 && !isExtensionEnabled(TExtension::EXT_draw_buffers))
                {
                    outOfRangeError(outOfRangeIndexIsError, location,
                                    "array index for gl_FragData must be zero when "
                                    "GL_EXT_draw_buffers is disabled",
                                    "[]");
                    safeIndex = 0;
                }
            }
            // Only do generic out-of-range check if similar error hasn't already been reported.
            if (safeIndex < 0)
            {
                if (baseExpression->isArray())
                {
                    safeIndex = checkIndexLessThan(outOfRangeIndexIsError, location, index,
                                                   baseExpression->getOutermostArraySize(),
                                                   "array index out of range");
                }
                else if (baseExpression->isMatrix())
                {
                    safeIndex = checkIndexLessThan(outOfRangeIndexIsError, location, index,
                                                   baseExpression->getType().getCols(),
                                                   "matrix field selection out of range");
                }
                else
                {
                    ASSERT(baseExpression->isVector());
                    safeIndex = checkIndexLessThan(outOfRangeIndexIsError, location, index,
                                                   baseExpression->getType().getNominalSize(),
                                                   "vector field selection out of range");
                }
            }

            ASSERT(safeIndex >= 0);
            // Data of constant unions can't be changed, because it may be shared with other
            // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new
            // sanitized object.
            if (safeIndex != index || indexConstantUnion->getBasicType() != EbtInt)
            {
                TConstantUnion *safeConstantUnion = new TConstantUnion();
                safeConstantUnion->setIConst(safeIndex);
                indexExpression =
                    new TIntermConstantUnion(safeConstantUnion, TType(indexExpression->getType()));
            }

            TIntermBinary *node =
                new TIntermBinary(EOpIndexDirect, baseExpression, indexExpression);
            node->setLine(location);

            if (baseExpression->isVector() && !baseExpression->isArray())
            {
                const uint32_t irIndex = mIRBuilder.popArraySize();
#ifdef ANGLE_IR
                ASSERT(!mCompileOptions.useIR || mDiagnostics->numErrors() > 0 ||
                       irIndex == static_cast<uint32_t>(index));
#endif
                mIRBuilder.vectorComponent(irIndex);
            }
            else
            {
                mIRBuilder.index();
            }

            return expressionOrFoldedResult(node);
        }
    }

    // According to ESSL 100 spec, Appendix A, the index expression must be a
    // constant-index-expression unless the operand is a uniform in a vertex shader.
    if (mValidateESSL100Limitations &&
        !(mShaderType == GL_VERTEX_SHADER && baseExpression->getQualifier() == EvqUniform))
    {
        checkESSL100ConstantIndex(indexExpression, location);
    }

    mIRBuilder.index();

    markStaticUseIfSymbol(indexExpression);
    TIntermBinary *node = new TIntermBinary(EOpIndexIndirect, baseExpression, indexExpression);
    node->setLine(location);
    // Indirect indexing can never be constant folded.
    return node;
}

int TParseContext::checkIndexLessThan(bool outOfRangeIndexIsError,
                                      const TSourceLoc &location,
                                      int index,
                                      unsigned int arraySize,
                                      const char *reason)
{
    // A negative index should already have been checked.
    ASSERT(index >= 0);
    if (static_cast<unsigned int>(index) >= arraySize)
    {
        std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
        reasonStream << reason << " '" << index << "'";
        std::string token = reasonStream.str();
        outOfRangeError(outOfRangeIndexIsError, location, reason, "[]");
        return arraySize - 1;
    }
    return index;
}

TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression,
                                                         const TSourceLoc &dotLocation,
                                                         const ImmutableString &fieldString,
                                                         const TSourceLoc &fieldLocation)
{
    if (baseExpression->isArray())
    {
        error(fieldLocation, "cannot apply dot operator to an array", ".");
        return baseExpression;
    }

    if (baseExpression->isVector())
    {
        TVector<uint32_t> fieldOffsets;
        if (!parseVectorFields(fieldLocation, fieldString, baseExpression->getNominalSize(),
                               &fieldOffsets))
        {
            fieldOffsets.resize(1);
            fieldOffsets[0] = 0;
        }

        if (fieldOffsets.size() == 1)
        {
            mIRBuilder.vectorComponent(fieldOffsets[0]);
        }
        else
        {
            ANGLE_UNSAFE_TODO(mIRBuilder.vectorComponentMulti(
                angle::Span(fieldOffsets.data(), fieldOffsets.size())));
        }

        TIntermSwizzle *node = new TIntermSwizzle(baseExpression, fieldOffsets);
        node->setLine(dotLocation);

        return node->fold(mDiagnostics);
    }
    else if (baseExpression->getBasicType() == EbtStruct)
    {
        const TFieldList &fields = baseExpression->getType().getStruct()->fields();
        if (fields.empty())
        {
            error(dotLocation, "structure has no fields", "Internal Error");
            return baseExpression;
        }
        else
        {
            bool fieldFound = false;
            unsigned int i;
            for (i = 0; i < fields.size(); ++i)
            {
                if (fields[i]->name() == fieldString)
                {
                    fieldFound = true;
                    break;
                }
            }
            if (fieldFound)
            {
                mIRBuilder.structField(i);

                // The AST RewriteStructSamplers transformation cannot handle (..., struct).sampler.
                // Fail compilation until the IR.
                if (!mCompileOptions.useIR && baseExpression->getAsBinaryNode() &&
                    baseExpression->getAsBinaryNode()->getOp() == EOpComma &&
                    baseExpression->getType().isStructureContainingSamplers())
                {
                    error(dotLocation,
                          "accessing fields of the result of a comma expression that is a "
                          "structure with samplers is not currently supported",
                          "Internal Error");
                }

                TIntermTyped *index = CreateIndexNode(i);
                index->setLine(fieldLocation);
                TIntermBinary *node =
                    new TIntermBinary(EOpIndexDirectStruct, baseExpression, index);
                node->setLine(dotLocation);
                return expressionOrFoldedResult(node);
            }
            else
            {
                error(dotLocation, " no such field in structure", fieldString);
                return baseExpression;
            }
        }
    }
    else if (baseExpression->isInterfaceBlock())
    {
        const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
        if (fields.empty())
        {
            error(dotLocation, "interface block has no fields", "Internal Error");
            return baseExpression;
        }
        else
        {
            bool fieldFound = false;
            unsigned int i;
            for (i = 0; i < fields.size(); ++i)
            {
                if (fields[i]->name() == fieldString)
                {
                    fieldFound = true;
                    break;
                }
            }
            if (fieldFound)
            {
                mIRBuilder.structField(i);

                // Validate extension requirements for gl_PerVertex fields.
                const TInterfaceBlock *interfaceBlock =
                    baseExpression->getType().getInterfaceBlock();
                if (interfaceBlock && interfaceBlock->name() == "gl_PerVertex")
                {
                    TQualifier fieldQualifier = fields[i]->type()->getQualifier();
                    if (fieldQualifier == EvqClipDistance || fieldQualifier == EvqCullDistance)
                    {
                        // gl_ClipDistance and gl_CullDistance require EXT_clip_cull_distance or
                        // ANGLE_clip_cull_distance extension.
                        if (!checkCanUseOneOfExtensions(
                                fieldLocation,
                                std::array<TExtension, 2u>{{TExtension::EXT_clip_cull_distance,
                                                            TExtension::ANGLE_clip_cull_distance}}))
                        {
                            return baseExpression;
                        }
                    }
                    else if (mShaderType == GL_GEOMETRY_SHADER && fieldQualifier == EvqPointSize)
                    {
                        if (!checkCanUseOneOfExtensions(
                                fieldLocation,
                                std::array<TExtension, 2u>{{TExtension::EXT_geometry_point_size,
                                                            TExtension::OES_geometry_point_size}}))
                        {
                            return baseExpression;
                        }
                    }
                    else if ((mShaderType == GL_TESS_CONTROL_SHADER ||
                              mShaderType == GL_TESS_EVALUATION_SHADER) &&
                             fieldQualifier == EvqPointSize)
                    {
                        if (!checkCanUseOneOfExtensions(
                                fieldLocation, std::array<TExtension, 2u>{
                                                   {TExtension::EXT_tessellation_point_size,
                                                    TExtension::OES_tessellation_point_size}}))
                        {
                            return baseExpression;
                        }
                    }
                }

                TIntermTyped *index = CreateIndexNode(i);
                index->setLine(fieldLocation);
                TIntermBinary *node =
                    new TIntermBinary(EOpIndexDirectInterfaceBlock, baseExpression, index);
                node->setLine(dotLocation);
                // Indexing interface blocks can never be constant folded.
                return node;
            }
            else
            {
                error(dotLocation, " no such field in interface block", fieldString);
                return baseExpression;
            }
        }
    }
    else
    {
        if (mShaderVersion < 300)
        {
            error(dotLocation, " field selection requires structure or vector on left hand side",
                  fieldString);
        }
        else
        {
            error(dotLocation,
                  " field selection requires structure, vector, or interface block on left hand "
                  "side",
                  fieldString);
        }
        return baseExpression;
    }
}

TLayoutQualifier TParseContext::parseLayoutQualifier(const ImmutableString &qualifierType,
                                                     const TSourceLoc &qualifierTypeLine)
{
    TLayoutQualifier qualifier = TLayoutQualifier::Create();

    if (qualifierType == "shared")
    {
        if (sh::IsWebGLBasedSpec(mShaderSpec))
        {
            error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "shared");
        }
        qualifier.blockStorage = EbsShared;
    }
    else if (qualifierType == "packed")
    {
        if (sh::IsWebGLBasedSpec(mShaderSpec))
        {
            error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "packed");
        }
        qualifier.blockStorage = EbsPacked;
    }
    else if (qualifierType == "std430")
    {
        checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
        qualifier.blockStorage = EbsStd430;
    }
    else if (qualifierType == "std140")
    {
        qualifier.blockStorage = EbsStd140;
    }
    else if (qualifierType == "row_major")
    {
        qualifier.matrixPacking = EmpRowMajor;
    }
    else if (qualifierType == "column_major")
    {
        qualifier.matrixPacking = EmpColumnMajor;
    }
    else if (qualifierType == "location")
    {
        error(qualifierTypeLine, "invalid layout qualifier: location requires an argument",
              qualifierType);
    }
    else if (qualifierType == "yuv" && mShaderType == GL_FRAGMENT_SHADER)
    {
        if (checkCanUseExtension(qualifierTypeLine, TExtension::EXT_YUV_target))
        {
            qualifier.yuv = true;
        }
    }
    else if (qualifierType == "early_fragment_tests")
    {
        checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
        qualifier.earlyFragmentTests = true;
    }
    else if (qualifierType == "rgba32f")
    {
        checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
        qualifier.imageInternalFormat = EiifRGBA32F;
    }
    else if (qualifierType == "rgba16f")
    {
        checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
        qualifier.imageInternalFormat = EiifRGBA16F;
    }
    else if (qualifierType == "r32f")
    {
        if (!isExtensionEnabled(TExtension::ANGLE_shader_pixel_local_storage))
        {
            checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
        }
        qualifier.imageInternalFormat = EiifR32F;
    }
    else if (qualifierType == "rgba8")
    {
        if (!isExtensionEnabled(TExtension::ANGLE_shader_pixel_local_storage))
        {
            checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
        }
        qualifier.imageInternalFormat = EiifRGBA8;
    }
    else if (qualifierType == "rgba8_snorm")
    {
        checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
        qualifier.imageInternalFormat = EiifRGBA8_SNORM;
    }
    else if (qualifierType == "rgba32i")
    {
        checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
        qualifier.imageInternalFormat = EiifRGBA32I;
    }
    else if (qualifierType == "rgba16i")
    {
        checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
        qualifier.imageInternalFormat = EiifRGBA16I;
    }
    else if (qualifierType == "rgba8i")
    {
        if (!isExtensionEnabled(TExtension::ANGLE_shader_pixel_local_storage))
        {
            checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
        }
        qualifier.imageInternalFormat = EiifRGBA8I;
    }
    else if (qualifierType == "r32i")
    {
        if (!isExtensionEnabled(TExtension::ANGLE_shader_pixel_local_storage))
        {
            checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
        }
        qualifier.imageInternalFormat = EiifR32I;
    }
    else if (qualifierType == "rgba32ui")
    {
        checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
        qualifier.imageInternalFormat = EiifRGBA32UI;
    }
    else if (qualifierType == "rgba16ui")
    {
        checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
        qualifier.imageInternalFormat = EiifRGBA16UI;
    }
    else if (qualifierType == "rgba8ui")
    {
        if (!isExtensionEnabled(TExtension::ANGLE_shader_pixel_local_storage))
        {
            checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
        }
        qualifier.imageInternalFormat = EiifRGBA8UI;
    }
    else if (qualifierType == "r32ui")
    {
        if (!isExtensionEnabled(TExtension::ANGLE_shader_pixel_local_storage))
        {
            checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
        }
        qualifier.imageInternalFormat = EiifR32UI;
    }
    else if (mShaderType == GL_GEOMETRY_SHADER_EXT &&
             (mShaderVersion >= 320 ||
              (checkCanUseOneOfExtensions(
                   qualifierTypeLine,
                   std::array<TExtension, 2u>{
                       {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}) &&
               checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310))))
    {
        if (qualifierType == "points")
        {
            qualifier.primitiveType = EptPoints;
        }
        else if (qualifierType == "lines")
        {
            qualifier.primitiveType = EptLines;
        }
        else if (qualifierType == "lines_adjacency")
        {
            qualifier.primitiveType = EptLinesAdjacency;
        }
        else if (qualifierType == "triangles")
        {
            qualifier.primitiveType = EptTriangles;
        }
        else if (qualifierType == "triangles_adjacency")
        {
            qualifier.primitiveType = EptTrianglesAdjacency;
        }
        else if (qualifierType == "line_strip")
        {
            qualifier.primitiveType = EptLineStrip;
        }
        else if (qualifierType == "triangle_strip")
        {
            qualifier.primitiveType = EptTriangleStrip;
        }
        else
        {
            error(qualifierTypeLine, "invalid layout qualifier", qualifierType);
        }
    }
    else if (mShaderType == GL_TESS_EVALUATION_SHADER_EXT &&
             (mShaderVersion >= 320 ||
              (checkCanUseOneOfExtensions(
                   qualifierTypeLine,
                   std::array<TExtension, 2u>{{TExtension::EXT_tessellation_shader,
                                               TExtension::OES_tessellation_shader}}) &&
               checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310))))
    {
        if (qualifierType == "triangles")
        {
            qualifier.tesPrimitiveType = EtetTriangles;
        }
        else if (qualifierType == "quads")
        {
            qualifier.tesPrimitiveType = EtetQuads;
        }
        else if (qualifierType == "isolines")
        {
            qualifier.tesPrimitiveType = EtetIsolines;
        }
        else if (qualifierType == "equal_spacing")
        {
            qualifier.tesVertexSpacingType = EtetEqualSpacing;
        }
        else if (qualifierType == "fractional_even_spacing")
        {
            qualifier.tesVertexSpacingType = EtetFractionalEvenSpacing;
        }
        else if (qualifierType == "fractional_odd_spacing")
        {
            qualifier.tesVertexSpacingType = EtetFractionalOddSpacing;
        }
        else if (qualifierType == "cw")
        {
            qualifier.tesOrderingType = EtetCw;
        }
        else if (qualifierType == "ccw")
        {
            qualifier.tesOrderingType = EtetCcw;
        }
        else if (qualifierType == "point_mode")
        {
            qualifier.tesPointType = EtetPointMode;
        }
        else
        {
            error(qualifierTypeLine, "invalid layout qualifier", qualifierType);
        }
    }
    else if (mShaderType == GL_FRAGMENT_SHADER)
    {
        if (qualifierType == "noncoherent")
        {
            if (checkCanUseOneOfExtensions(
                    qualifierTypeLine, std::array<TExtension, 3u>{
                                           {TExtension::EXT_shader_framebuffer_fetch,
                                            TExtension::EXT_shader_framebuffer_fetch_non_coherent,
                                            TExtension::ANGLE_shader_pixel_local_storage}}))
            {
                checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 100);
                qualifier.noncoherent = true;
            }
        }
        else if (qualifierType == "blend_support_multiply")
        {
            AddAdvancedBlendEquation(gl::BlendEquationType::Multiply, &qualifier);
        }
        else if (qualifierType == "blend_support_screen")
        {
            AddAdvancedBlendEquation(gl::BlendEquationType::Screen, &qualifier);
        }
        else if (qualifierType == "blend_support_overlay")
        {
            AddAdvancedBlendEquation(gl::BlendEquationType::Overlay, &qualifier);
        }
        else if (qualifierType == "blend_support_darken")
        {
            AddAdvancedBlendEquation(gl::BlendEquationType::Darken, &qualifier);
        }
        else if (qualifierType == "blend_support_lighten")
        {
            AddAdvancedBlendEquation(gl::BlendEquationType::Lighten, &qualifier);
        }
        else if (qualifierType == "blend_support_colordodge")
        {
            AddAdvancedBlendEquation(gl::BlendEquationType::Colordodge, &qualifier);
        }
        else if (qualifierType == "blend_support_colorburn")
        {
            AddAdvancedBlendEquation(gl::BlendEquationType::Colorburn, &qualifier);
        }
        else if (qualifierType == "blend_support_hardlight")
        {
            AddAdvancedBlendEquation(gl::BlendEquationType::Hardlight, &qualifier);
        }
        else if (qualifierType == "blend_support_softlight")
        {
            AddAdvancedBlendEquation(gl::BlendEquationType::Softlight, &qualifier);
        }
        else if (qualifierType == "blend_support_difference")
        {
            AddAdvancedBlendEquation(gl::BlendEquationType::Difference, &qualifier);
        }
        else if (qualifierType == "blend_support_exclusion")
        {
            AddAdvancedBlendEquation(gl::BlendEquationType::Exclusion, &qualifier);
        }
        else if (qualifierType == "blend_support_hsl_hue")
        {
            AddAdvancedBlendEquation(gl::BlendEquationType::HslHue, &qualifier);
        }
        else if (qualifierType == "blend_support_hsl_saturation")
        {
            AddAdvancedBlendEquation(gl::BlendEquationType::HslSaturation, &qualifier);
        }
        else if (qualifierType == "blend_support_hsl_color")
        {
            AddAdvancedBlendEquation(gl::BlendEquationType::HslColor, &qualifier);
        }
        else if (qualifierType == "blend_support_hsl_luminosity")
        {
            AddAdvancedBlendEquation(gl::BlendEquationType::HslLuminosity, &qualifier);
        }
        else if (qualifierType == "blend_support_all_equations")
        {
            qualifier.advancedBlendEquations.setAll();
        }
        else if (qualifierType == "depth_any")
        {
            qualifier.depth = EdAny;
        }
        else if (qualifierType == "depth_greater")
        {
            qualifier.depth = EdGreater;
        }
        else if (qualifierType == "depth_less")
        {
            qualifier.depth = EdLess;
        }
        else if (qualifierType == "depth_unchanged" && !sh::IsWebGLBasedSpec(mShaderSpec))
        {
            qualifier.depth = EdUnchanged;
        }
        else
        {
            error(qualifierTypeLine, "invalid layout qualifier", qualifierType);
        }

        if (qualifier.advancedBlendEquations.any() && mShaderVersion < 320)
        {
            if (!checkCanUseExtension(qualifierTypeLine, TExtension::KHR_blend_equation_advanced))
            {
                qualifier.advancedBlendEquations.reset();
            }
        }
    }
    else
    {
        error(qualifierTypeLine, "invalid layout qualifier", qualifierType);
    }

    return qualifier;
}

void TParseContext::parseLocalSize(const ImmutableString &qualifierType,
                                   const TSourceLoc &qualifierTypeLine,
                                   int intValue,
                                   const TSourceLoc &intValueLine,
                                   const std::string &intValueString,
                                   size_t index,
                                   sh::WorkGroupSize *localSize)
{
    checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
    if (intValue < 1)
    {
        std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
        reasonStream << "out of range: " << getWorkGroupSizeString(index) << " must be positive";
        std::string reason = reasonStream.str();
        error(intValueLine, reason.c_str(), intValueString.c_str());
    }
    (*localSize)[index] = intValue;
}

void TParseContext::parseNumViews(int intValue,
                                  const TSourceLoc &intValueLine,
                                  const std::string &intValueString,
                                  int *numViews)
{
    // This error is only specified in WebGL, but tightens unspecified behavior in the native
    // specification.
    if (intValue < 1)
    {
        error(intValueLine, "out of range: num_views must be positive", intValueString.c_str());
    }
    *numViews = intValue;
}

void TParseContext::parseInvocations(int intValue,
                                     const TSourceLoc &intValueLine,
                                     const std::string &intValueString,
                                     int *numInvocations)
{
    // Although SPEC isn't clear whether invocations can be less than 1, we add this limit because
    // it doesn't make sense to accept invocations <= 0.
    if (intValue < 1 || intValue > mResources.MaxGeometryShaderInvocations)
    {
        error(intValueLine,
              "out of range: invocations must be in the range of [1, "
              "MAX_GEOMETRY_SHADER_INVOCATIONS_OES]",
              intValueString.c_str());
    }
    else
    {
        *numInvocations = intValue;
    }
}

void TParseContext::parseMaxVertices(int intValue,
                                     const TSourceLoc &intValueLine,
                                     const std::string &intValueString,
                                     int *maxVertices)
{
    // Although SPEC isn't clear whether max_vertices can be less than 0, we add this limit because
    // it doesn't make sense to accept max_vertices < 0.
    if (intValue < 0 || intValue > mResources.MaxGeometryOutputVertices)
    {
        error(
            intValueLine,
            "out of range: max_vertices must be in the range of [0, gl_MaxGeometryOutputVertices]",
            intValueString.c_str());
    }
    else
    {
        *maxVertices = intValue;
    }
}

void TParseContext::parseVertices(int intValue,
                                  const TSourceLoc &intValueLine,
                                  const std::string &intValueString,
                                  int *vertices)
{
    if (intValue < 1 || intValue > mResources.MaxPatchVertices)
    {
        error(intValueLine,
              "out of range : vertices must be in the range of [1, gl_MaxPatchVertices]",
              intValueString.c_str());
    }
    else
    {
        *vertices = intValue;
    }
}

void TParseContext::parseIndexLayoutQualifier(int intValue,
                                              const TSourceLoc &intValueLine,
                                              const std::string &intValueString,
                                              int *index)
{
    // EXT_blend_func_extended specifies that most validation should happen at link time, but since
    // we're validating output variable locations at compile time, it makes sense to validate that
    // index is 0 or 1 also at compile time. Also since we use "-1" as a placeholder for unspecified
    // index, we can't accept it here.
    if (intValue < 0 || intValue > 1)
    {
        error(intValueLine, "out of range: index layout qualifier can only be 0 or 1",
              intValueString.c_str());
    }
    else
    {
        *index = intValue;
    }
}

TLayoutQualifier TParseContext::parseLayoutQualifier(const ImmutableString &qualifierType,
                                                     const TSourceLoc &qualifierTypeLine,
                                                     int intValue,
                                                     const TSourceLoc &intValueLine)
{
    TLayoutQualifier qualifier = TLayoutQualifier::Create();

    std::string intValueString = Str(intValue);

    if (qualifierType == "location")
    {
        // must check that location is non-negative
        if (intValue < 0)
        {
            error(intValueLine, "out of range: location must be non-negative",
                  intValueString.c_str());
        }
        else
        {
            qualifier.location           = intValue;
            qualifier.locationsSpecified = 1;
        }
    }
    else if (qualifierType == "binding")
    {
        if (!isExtensionEnabled(TExtension::ANGLE_shader_pixel_local_storage))
        {
            checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
        }
        if (intValue < 0)
        {
            error(intValueLine, "out of range: binding must be non-negative",
                  intValueString.c_str());
        }
        else
        {
            qualifier.binding = intValue;
        }
    }
    else if (qualifierType == "offset")
    {
        checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
        if (intValue < 0)
        {
            error(intValueLine, "out of range: offset must be non-negative",
                  intValueString.c_str());
        }
        else
        {
            qualifier.offset = intValue;
        }
    }
    else if (qualifierType == "local_size_x")
    {
        parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 0u,
                       &qualifier.localSize);
    }
    else if (qualifierType == "local_size_y")
    {
        parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 1u,
                       &qualifier.localSize);
    }
    else if (qualifierType == "local_size_z")
    {
        parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u,
                       &qualifier.localSize);
    }
    else if (qualifierType == "num_views" && mShaderType == GL_VERTEX_SHADER)
    {
        if (checkCanUseOneOfExtensions(
                qualifierTypeLine, std::array<TExtension, 2u>{
                                       {TExtension::OVR_multiview, TExtension::OVR_multiview2}}))
        {
            parseNumViews(intValue, intValueLine, intValueString, &qualifier.numViews);
        }
    }
    else if (qualifierType == "invocations" && mShaderType == GL_GEOMETRY_SHADER_EXT &&
             (mShaderVersion >= 320 ||
              checkCanUseOneOfExtensions(
                  qualifierTypeLine,
                  std::array<TExtension, 2u>{
                      {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}})))
    {
        parseInvocations(intValue, intValueLine, intValueString, &qualifier.invocations);
    }
    else if (qualifierType == "max_vertices" && mShaderType == GL_GEOMETRY_SHADER_EXT &&
             (mShaderVersion >= 320 ||
              checkCanUseOneOfExtensions(
                  qualifierTypeLine,
                  std::array<TExtension, 2u>{
                      {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}})))
    {
        parseMaxVertices(intValue, intValueLine, intValueString, &qualifier.maxVertices);
    }
    else if (qualifierType == "index" && mShaderType == GL_FRAGMENT_SHADER &&
             checkCanUseExtension(qualifierTypeLine, TExtension::EXT_blend_func_extended))
    {
        parseIndexLayoutQualifier(intValue, intValueLine, intValueString, &qualifier.index);
        if (intValue != 0)
        {
            errorIfPLSDeclared(qualifierTypeLine, PLSIllegalOperations::FragDataIndexNonzero);
        }
    }
    else if (qualifierType == "vertices" && mShaderType == GL_TESS_CONTROL_SHADER_EXT &&
             (mShaderVersion >= 320 ||
              checkCanUseOneOfExtensions(
                  qualifierTypeLine,
                  std::array<TExtension, 2u>{
                      {TExtension::EXT_tessellation_shader, TExtension::OES_tessellation_shader}})))
    {
        parseVertices(intValue, intValueLine, intValueString, &qualifier.vertices);
    }
    else
    {
        error(qualifierTypeLine, "invalid layout qualifier", qualifierType);
    }

    return qualifier;
}

TTypeQualifierBuilder *TParseContext::createTypeQualifierBuilder(const TSourceLoc &loc)
{
    return new TTypeQualifierBuilder(
        new TStorageQualifierWrapper(symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary, loc),
        mShaderVersion);
}

TStorageQualifierWrapper *TParseContext::parseGlobalStorageQualifier(TQualifier qualifier,
                                                                     const TSourceLoc &loc)
{
    checkIsAtGlobalLevel(loc, getQualifierString(qualifier));
    return new TStorageQualifierWrapper(qualifier, loc);
}

TStorageQualifierWrapper *TParseContext::parseVaryingQualifier(const TSourceLoc &loc)
{
    if (getShaderType() == GL_VERTEX_SHADER)
    {
        return parseGlobalStorageQualifier(EvqVaryingOut, loc);
    }
    return parseGlobalStorageQualifier(EvqVaryingIn, loc);
}

TStorageQualifierWrapper *TParseContext::parseInQualifier(const TSourceLoc &loc)
{
    if (declaringFunction())
    {
        return new TStorageQualifierWrapper(EvqParamIn, loc);
    }

    switch (getShaderType())
    {
        case GL_VERTEX_SHADER:
        {
            if (mShaderVersion < 300 && !anyMultiviewExtensionAvailable())
            {
                error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
            }
            return new TStorageQualifierWrapper(EvqVertexIn, loc);
        }
        case GL_FRAGMENT_SHADER:
        {
            if (mShaderVersion < 300)
            {
                error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
            }
            return new TStorageQualifierWrapper(EvqFragmentIn, loc);
        }
        case GL_COMPUTE_SHADER:
        {
            return new TStorageQualifierWrapper(EvqComputeIn, loc);
        }
        case GL_GEOMETRY_SHADER:
        {
            return new TStorageQualifierWrapper(EvqGeometryIn, loc);
        }
        case GL_TESS_CONTROL_SHADER:
        {
            return new TStorageQualifierWrapper(EvqTessControlIn, loc);
        }
        case GL_TESS_EVALUATION_SHADER:
        {
            return new TStorageQualifierWrapper(EvqTessEvaluationIn, loc);
        }
        default:
        {
            UNREACHABLE();
            return new TStorageQualifierWrapper(EvqLast, loc);
        }
    }
}

TStorageQualifierWrapper *TParseContext::parseOutQualifier(const TSourceLoc &loc)
{
    if (declaringFunction())
    {
        return new TStorageQualifierWrapper(EvqParamOut, loc);
    }
    switch (getShaderType())
    {
        case GL_VERTEX_SHADER:
        {
            if (mShaderVersion < 300)
            {
                error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "out");
            }
            return new TStorageQualifierWrapper(EvqVertexOut, loc);
        }
        case GL_FRAGMENT_SHADER:
        {
            if (mShaderVersion < 300)
            {
                error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "out");
            }
            return new TStorageQualifierWrapper(EvqFragmentOut, loc);
        }
        case GL_COMPUTE_SHADER:
        {
            error(loc, "storage qualifier isn't supported in compute shaders", "out");
            return new TStorageQualifierWrapper(EvqParamOut, loc);
        }
        case GL_GEOMETRY_SHADER_EXT:
        {
            return new TStorageQualifierWrapper(EvqGeometryOut, loc);
        }
        case GL_TESS_CONTROL_SHADER_EXT:
        {
            return new TStorageQualifierWrapper(EvqTessControlOut, loc);
        }
        case GL_TESS_EVALUATION_SHADER_EXT:
        {
            return new TStorageQualifierWrapper(EvqTessEvaluationOut, loc);
        }
        default:
        {
            UNREACHABLE();
            return new TStorageQualifierWrapper(EvqLast, loc);
        }
    }
}

TStorageQualifierWrapper *TParseContext::parseInOutQualifier(const TSourceLoc &loc)
{
    if (!declaringFunction())
    {
        if (mShaderVersion < 300)
        {
            error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "inout");
        }

        if (getShaderType() != GL_FRAGMENT_SHADER)
        {
            error(loc, "storage qualifier isn't supported in non-fragment shaders", "inout");
        }

        if (isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch) ||
            isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch_non_coherent))
        {
            return new TStorageQualifierWrapper(EvqFragmentInOut, loc);
        }

        error(loc,
              "invalid qualifier: can be used with either function parameters or the variables for "
              "fetching input attachment data",
              "inout");
    }
    return new TStorageQualifierWrapper(EvqParamInOut, loc);
}

TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
                                                     TLayoutQualifier rightQualifier,
                                                     const TSourceLoc &rightQualifierLocation)
{
    return sh::JoinLayoutQualifiers(leftQualifier, rightQualifier, rightQualifierLocation,
                                    mDiagnostics);
}

TDeclarator *TParseContext::parseStructDeclarator(const ImmutableString &identifier,
                                                  const TSourceLoc &loc)
{
    return new TDeclarator(identifier, loc);
}

TDeclarator *TParseContext::parseStructArrayDeclarator(const ImmutableString &identifier,
                                                       const TSourceLoc &loc,
                                                       const TVector<unsigned int> *arraySizes)
{
    return new TDeclarator(identifier, arraySizes, loc);
}

void TParseContext::checkDoesNotHaveDuplicateFieldNames(const TFieldList *fields,
                                                        const TSourceLoc &location)
{
    TUnorderedMap<ImmutableString, uint32_t, ImmutableString::FowlerNollVoHash<sizeof(size_t)>>
        fieldNames;
    for (TField *field : *fields)
    {
        // Note: operator[] adds this name to the map if it doesn't already exist, and initializes
        // its value to 0.
        uint32_t count = ++fieldNames[field->name()];
        if (count != 1)
        {
            error(location, "Duplicate field name in structure", field->name());
        }
    }
}

void TParseContext::checkDoesNotHaveTooManyFields(const ImmutableString &name,
                                                  const TFieldList *fields,
                                                  const TSourceLoc &location)
{
    // Check that there are not too many fields.  SPIR-V has a limit of 16383 fields, and it would
    // be reasonable to apply that limit to all outputs.  For example, it was observed that 32768
    // fields cause the Nvidia GL driver to fail compilation, so such a limit is not too specific to
    // SPIR-V.
    constexpr size_t kMaxFieldCount = 16383;
    if (fields->size() > kMaxFieldCount)
    {
        error(location, "Too many fields in the struct (limit is 16383)", name);
    }
}

TFieldList *TParseContext::addStructFieldList(TFieldList *fields, const TSourceLoc &location)
{
    return fields;
}

TFieldList *TParseContext::combineStructFieldLists(TFieldList *processedFields,
                                                   const TFieldList *newlyAddedFields,
                                                   const TSourceLoc &location)
{
    processedFields->insert(processedFields->end(), newlyAddedFields->begin(),
                            newlyAddedFields->end());
    return processedFields;
}

TFieldList *TParseContext::addStructDeclaratorListWithQualifiers(
    const TTypeQualifierBuilder &typeQualifierBuilder,
    TPublicType *typeSpecifier,
    const TDeclaratorList *declaratorList)
{
    TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);

    typeSpecifier->qualifier       = typeQualifier.qualifier;
    typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier;
    typeSpecifier->memoryQualifier = typeQualifier.memoryQualifier;
    typeSpecifier->invariant       = typeQualifier.invariant;
    typeSpecifier->precise         = typeQualifier.precise;
    if (typeQualifier.precision != EbpUndefined)
    {
        typeSpecifier->precision = typeQualifier.precision;
    }
    return addStructDeclaratorList(*typeSpecifier, declaratorList);
}

TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
                                                   const TDeclaratorList *declaratorList)
{
    checkPrecisionSpecified(typeSpecifier.getLine(), typeSpecifier.precision,
                            typeSpecifier.getBasicType());

    checkIsNonVoid(typeSpecifier.getLine(), (*declaratorList)[0]->name(),
                   typeSpecifier.getBasicType());

    checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), typeSpecifier.layoutQualifier);
    checkEarlyFragmentTestsIsNotSpecified(typeSpecifier.getLine(),
                                          typeSpecifier.layoutQualifier.earlyFragmentTests);
    checkNoncoherentIsNotSpecified(typeSpecifier.getLine(),
                                   typeSpecifier.layoutQualifier.noncoherent);

    TFieldList *fieldList = new TFieldList();

    for (const TDeclarator *declarator : *declaratorList)
    {
        TType *type = new TType(typeSpecifier);

        if (declarator->isArray())
        {
            // Don't allow arrays of arrays in ESSL < 3.10.
            checkArrayElementIsNotArray(typeSpecifier.getLine(), typeSpecifier);
            type->makeArrays(*declarator->arraySizes());
        }
        type->setTypeId(getTypeId(*type));

        SymbolType symbolType = SymbolType::UserDefined;
        if (declarator->name() == "gl_Position" || declarator->name() == "gl_PointSize" ||
            declarator->name() == "gl_ClipDistance" || declarator->name() == "gl_CullDistance")
        {
            symbolType = SymbolType::BuiltIn;
        }
        else
        {
            checkIsNotReserved(typeSpecifier.getLine(), declarator->name());
        }
        TField *field = new TField(type, declarator->name(), declarator->line(), symbolType);
        checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *field);
        fieldList->push_back(field);
    }

    return fieldList;
}

TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
                                                   const TSourceLoc &nameLine,
                                                   const ImmutableString &structName,
                                                   TFieldList *fieldList)
{
    SymbolType structSymbolType = SymbolType::UserDefined;
    const bool isNamelessStruct = structName.empty();
    if (isNamelessStruct)
    {
        structSymbolType = SymbolType::Empty;
    }

    // To simplify pulling samplers out of structs, reorder the struct fields to put the samplers at
    // the end.  Structures that *only* contain samplers are also put last.
    TFieldList *reorderedFields = new TFieldList;
    for (TField *field : *fieldList)
    {
        if (!IsSamplerOrStructWithOnlySamplers(field->type()))
        {
            reorderedFields->push_back(field);
        }
    }
    for (TField *field : *fieldList)
    {
        if (IsSamplerOrStructWithOnlySamplers(field->type()))
        {
            reorderedFields->push_back(field);
        }
    }

    TStructure *structure =
        new TStructure(&symbolTable, structName, reorderedFields, structSymbolType);

    // Store a bool in the struct if we're at global scope, to allow us to
    // skip the local struct scoping workaround in HLSL.
    structure->setAtGlobalScope(symbolTable.atGlobalLevel());

    if (structSymbolType != SymbolType::Empty)
    {
        checkIsNotReserved(nameLine, structName);
        if (!symbolTable.declare(structure))
        {
            error(nameLine, "redefinition of a struct", structName);
        }
    }

    checkDoesNotHaveTooManyFields(structName, fieldList, structLine);

    // Ensure there are no duplicate field names
    checkDoesNotHaveDuplicateFieldNames(fieldList, structLine);

    // Ensure we do not specify any storage qualifiers on the struct members
    for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
    {
        TField &field              = *(*fieldList)[typeListIndex];
        const TQualifier qualifier = field.type()->getQualifier();
        switch (qualifier)
        {
            case EvqGlobal:
            case EvqTemporary:
                break;
            default:
                error(field.line(), "invalid qualifier on struct member",
                      getQualifierString(qualifier));
                break;
        }
        if (field.type()->isInvariant())
        {
            error(field.line(), "invalid qualifier on struct member", "invariant");
        }

        const TLayoutQualifier layoutQualifier = field.type()->getLayoutQualifier();
        if (!layoutQualifier.isEmpty())
        {
            error(field.line(), "invalid layout qualifier on struct member", "layout");
        }

        const TMemoryQualifier memoryQualifier = field.type()->getMemoryQualifier();
        if (!memoryQualifier.isEmpty())
        {
            error(field.line(), "invalid memory qualifier on struct member",
                  memoryQualifier.getAnyQualifierString());
        }

        if (field.type()->isPrecise())
        {
            error(field.line(), "invalid precise qualifier on struct member", "precise");
        }

        // ESSL 3.10 section 4.1.8 -- atomic_uint or images are not allowed as structure member.
        // ANGLE_shader_pixel_local_storage also disallows PLS as struct members.
        if (IsImage(field.type()->getBasicType()) ||
            IsAtomicCounter(field.type()->getBasicType()) ||
            IsPixelLocal(field.type()->getBasicType()))
        {
            error(field.line(), "disallowed type in struct", field.type()->getBasicString());
        }

        checkIsNotUnsizedArray(field.line(), "array members of structs must specify a size",
                               field.name(), field.type());

        checkMemoryQualifierIsNotSpecified(field.type()->getMemoryQualifier(), field.line());

        checkIndexIsNotSpecified(field.line(), field.type()->getLayoutQualifier().index);

        checkBindingIsNotSpecified(field.line(), field.type()->getLayoutQualifier().binding);

        checkLocationIsNotSpecified(field.line(), field.type()->getLayoutQualifier());
    }

    mSymbolToTypeId[structure] = mIRBuilder.getStructTypeId(
        structure->symbolType() == SymbolType::Empty ? kEmptyImmutableString : structure->name(),
        ANGLE_UNSAFE_TODO(
            angle::Span<const TField *const>(reorderedFields->data(), reorderedFields->size())),
        {}, false, false, symbolTable.atGlobalLevel());

    // Nameless structs are declared inline with their variables.  But named structs are always
    // separately declared at the end of parse.
    TTypeSpecifierNonArray typeSpecifierNonArray;
    typeSpecifierNonArray.initializeStruct(structure, isNamelessStruct, true, structLine);
    exitStructDeclaration();

    if (!isNamelessStruct)
    {
        if (symbolTable.atGlobalLevel())
        {
            mGlobalNamedStructs.push_back(structure);
        }
        else
        {
            mFunctionLocalNamedStructs.push_back(structure);
        }
    }

    return typeSpecifierNonArray;
}

void TParseContext::beginSwitch(const TSourceLoc &line, TIntermTyped *init)
{
    ControlFlow flow = {};
    flow.type        = ControlFlowType::Switch;
    flow.switchType  = init->getBasicType();
    mControlFlow.push_back(flow);

    symbolTable.push();

    checkNestingLevel(line);

    mIRBuilder.beginSwitch();
}

TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
                                        TIntermBlock *statementList,
                                        const TSourceLoc &loc)
{
    symbolTable.pop();
    popControlFlow();

    TBasicType switchType = init->getBasicType();
    if ((switchType != EbtInt && switchType != EbtUInt) || init->isMatrix() || init->isArray() ||
        init->isVector())
    {
        error(init->getLine(), "init-expression in a switch statement must be a scalar integer",
              "switch");
        return nullptr;
    }

    ASSERT(statementList);

    // There have been some differences between versions of GLSL ES specs on whether this should
    // be an error or not, but this was clarified as an error in GLSL ES versions newer than 3.00
    // too.
    const size_t statementCount = statementList->getChildCount();
    if (statementCount > 0 &&
        statementList->getChildNode(statementCount - 1)->getAsCaseNode() != nullptr)
    {
        error(loc, "no statement between the last case label and the end of the switch statement",
              "switch");
        return nullptr;
    }

    // In case the last statement isn't already a branch, add |break| automatically.  Some AST
    // transformations may dead-code-eliminate the contents of the last |case| and leave the switch
    // statements ending in a case (which is what the check above forbids).  Most generators do not
    // handle this unexpected situation.
    //
    // Note that a branch may be present inside a nested block, but that's ok, the extra branch
    // added here gets eliminated in |PruneNoOps|.
    if (statementCount > 0 &&
        statementList->getChildNode(statementCount - 1)->getAsBranchNode() == nullptr)
    {
        statementList->appendStatement(new TIntermBranch(EOpBreak, nullptr));
    }

    mIRBuilder.endSwitch();

    markStaticUseIfSymbol(init);
    TIntermSwitch *node = new TIntermSwitch(init, statementList);
    node->setLine(loc);
    return node;
}

bool TParseContext::isNestedIn(ControlFlowType type) const
{
    // Used for validation, we need to know for example that a `continue` statement is nested
    // within a loop, etc.  Search backwards in the nested control flow info to find the closest
    // control flow of given type.
    for (auto iter = mControlFlow.rbegin(); iter != mControlFlow.rend(); ++iter)
    {
        if (iter->type == type)
        {
            return true;
        }
    }
    return false;
}

bool TParseContext::isDirectlyUnderSwitch() const
{
    return mControlFlow.size() > 0 && mControlFlow.back().type == ControlFlowType::Switch;
}

bool TParseContext::checkCase(const TSourceLoc &line, int64_t caseValue, const char *caseOrDefault)
{
    if (!isDirectlyUnderSwitch())
    {
        error(line, "case and default labels need to be inside switch statements", caseOrDefault);
        return false;
    }
    for (int64_t existingCaseLabel : mControlFlow.back().caseLabels)
    {
        if (caseValue == existingCaseLabel)
        {
            error(line, "duplicate case label", caseOrDefault);
            return false;
        }
    }

    mControlFlow.back().caseLabels.push_back(caseValue);

    return true;
}

TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
{
    if (condition == nullptr)
    {
        error(loc, "case label must have a condition", "case");
        return nullptr;
    }
    if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
        condition->isMatrix() || condition->isArray() || condition->isVector())
    {
        error(condition->getLine(), "case label must be a scalar integer", "case");
        return nullptr;
    }
    TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
    // ANGLE should be able to fold any EvqConst expressions resulting in an integer - but to be
    // safe against corner cases we still check for conditionConst. Some interpretations of the
    // spec have allowed constant expressions with side effects - like array length() method on a
    // non-constant array.
    if (condition->getQualifier() != EvqConst || conditionConst == nullptr)
    {
        error(condition->getLine(), "case label must be constant", "case");
        return nullptr;
    }

    const int64_t caseValue = condition->getBasicType() == EbtInt
                                  ? static_cast<int64_t>(conditionConst->getIConst(0))
                                  : static_cast<int64_t>(conditionConst->getUConst(0));
    if (!checkCase(loc, caseValue, "case"))
    {
        return nullptr;
    }

    if (condition->getBasicType() != mControlFlow.back().switchType)
    {
        error(loc, "case label type does not match switch init-expression type", "case");
    }

    mIRBuilder.beginCase();

    TIntermCase *node = new TIntermCase(condition);
    node->setLine(loc);
    return node;
}

TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
{
    if (!checkCase(loc, ControlFlow::kDefaultCaseLabel, "default"))
    {
        return nullptr;
    }

    mIRBuilder.beginDefault();

    TIntermCase *node = new TIntermCase(nullptr);
    node->setLine(loc);
    return node;
}

TIntermTyped *TParseContext::createUnaryMath(TOperator op,
                                             TIntermTyped *child,
                                             const TSourceLoc &loc,
                                             const TFunction *func)
{
    ASSERT(child != nullptr);

    switch (op)
    {
        case EOpLogicalNot:
            if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() ||
                child->isVector())
            {
                unaryOpError(loc, GetOperatorString(op), child->getType());
                return nullptr;
            }
            break;
        case EOpBitwiseNot:
            if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
                child->isMatrix() || child->isArray())
            {
                unaryOpError(loc, GetOperatorString(op), child->getType());
                return nullptr;
            }
            break;
        case EOpPostIncrement:
        case EOpPreIncrement:
        case EOpPostDecrement:
        case EOpPreDecrement:
        case EOpNegative:
        case EOpPositive:
            if (child->getBasicType() == EbtStruct || child->isInterfaceBlock() ||
                child->getBasicType() == EbtBool || child->isArray() ||
                child->getBasicType() == EbtVoid || IsOpaqueType(child->getBasicType()))
            {
                unaryOpError(loc, GetOperatorString(op), child->getType());
                return nullptr;
            }
            break;
        // Operators for math built-ins are already type checked against their prototype.
        default:
            break;
    }

    if (child->getMemoryQualifier().writeonly)
    {
        const char *opStr =
            BuiltInGroup::IsBuiltIn(op) ? func->name().data() : GetOperatorString(op);
        unaryOpError(loc, opStr, child->getType());
        return nullptr;
    }

    mIRBuilder.builtIn(op, 1);

    markStaticUseIfSymbol(child);
    TIntermUnary *node = new TIntermUnary(op, child, func);
    node->setLine(loc);

    return node->fold(mDiagnostics);
}

TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
{
    ASSERT(op != EOpNull);
    TIntermTyped *node = createUnaryMath(op, child, loc, nullptr);
    if (node == nullptr)
    {
        return child;
    }
    return node;
}

TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op,
                                                TIntermTyped *child,
                                                const TSourceLoc &loc)
{
    checkCanBeLValue(loc, GetOperatorString(op), child);
    return addUnaryMath(op, child, loc);
}

TIntermTyped *TParseContext::expressionOrFoldedResult(TIntermTyped *expression)
{
    // If we can, we should return the folded version of the expression for subsequent parsing. This
    // enables folding the containing expression during parsing as well, instead of the separate
    // FoldExpressions() step where folding nested expressions requires multiple full AST
    // traversals.

    // Even if folding fails the fold() functions return some node representing the expression,
    // typically the original node. So "folded" can be assumed to be non-null.
    TIntermTyped *folded = expression->fold(mDiagnostics);
    ASSERT(folded != nullptr);
    if (folded->getQualifier() == expression->getQualifier())
    {
        // We need this expression to have the correct qualifier when validating the consuming
        // expression. So we can only return the folded node from here in case it has the same
        // qualifier as the original expression. In this kind of a cases the qualifier of the folded
        // node is EvqConst, whereas the qualifier of the expression is EvqTemporary:
        //  1. (true ? 1.0 : non_constant)
        //  2. (non_constant, 1.0)
        return folded;
    }
    return expression;
}

bool TParseContext::binaryOpCommonCheck(TOperator op,
                                        TIntermTyped *left,
                                        TIntermTyped *right,
                                        const TSourceLoc &loc)
{
    if (left->getBasicType() == EbtVoid || right->getBasicType() == EbtVoid)
    {
        error(loc, "operation with void operands", GetOperatorString(op));
        return false;
    }
    // Check opaque types are not allowed to be operands in expressions other than array indexing
    // and structure member selection.
    if (IsOpaqueType(left->getBasicType()) || IsOpaqueType(right->getBasicType()))
    {
        switch (op)
        {
            case EOpIndexDirect:
            case EOpIndexIndirect:
                break;

            default:
                ASSERT(op != EOpIndexDirectStruct);
                error(loc, "Invalid operation for variables with an opaque type",
                      GetOperatorString(op));
                return false;
        }
    }

    if (right->getMemoryQualifier().writeonly)
    {
        error(loc, "Invalid operation for variables with writeonly", GetOperatorString(op));
        return false;
    }

    if (left->getMemoryQualifier().writeonly)
    {
        switch (op)
        {
            case EOpAssign:
            case EOpInitialize:
            case EOpIndexDirect:
            case EOpIndexIndirect:
            case EOpIndexDirectStruct:
            case EOpIndexDirectInterfaceBlock:
                break;
            default:
                error(loc, "Invalid operation for variables with writeonly", GetOperatorString(op));
                return false;
        }
    }

    if (left->getType().getStruct() || right->getType().getStruct())
    {
        switch (op)
        {
            case EOpIndexDirectStruct:
                ASSERT(left->getType().getStruct());
                break;
            case EOpEqual:
            case EOpNotEqual:
            case EOpAssign:
            case EOpInitialize:
                if (left->getType() != right->getType())
                {
                    return false;
                }
                break;
            default:
                error(loc, "Invalid operation for structs", GetOperatorString(op));
                return false;
        }
    }

    if (left->isInterfaceBlock() || right->isInterfaceBlock())
    {
        switch (op)
        {
            case EOpIndexDirectInterfaceBlock:
                ASSERT(left->getType().getInterfaceBlock());
                break;
            default:
                error(loc, "Invalid operation for interface blocks", GetOperatorString(op));
                return false;
        }
    }

    if (left->isArray() != right->isArray())
    {
        error(loc, "array / non-array mismatch", GetOperatorString(op));
        return false;
    }

    if (left->isArray())
    {
        ASSERT(right->isArray());
        if (mShaderVersion < 300)
        {
            error(loc, "Invalid operation for arrays", GetOperatorString(op));
            return false;
        }

        switch (op)
        {
            case EOpEqual:
            case EOpNotEqual:
            case EOpAssign:
            case EOpInitialize:
                break;
            default:
                error(loc, "Invalid operation for arrays", GetOperatorString(op));
                return false;
        }
        // At this point, size of implicitly sized arrays should be resolved.
        if (left->getType().getArraySizes() != right->getType().getArraySizes())
        {
            error(loc, "array size mismatch", GetOperatorString(op));
            return false;
        }
    }

    // Check ops which require integer / ivec parameters
    bool isBitShift = false;
    switch (op)
    {
        case EOpBitShiftLeft:
        case EOpBitShiftRight:
        case EOpBitShiftLeftAssign:
        case EOpBitShiftRightAssign:
            // Unsigned can be bit-shifted by signed and vice versa, but we need to
            // check that the basic type is an integer type.
            isBitShift = true;
            if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
            {
                return false;
            }
            break;
        case EOpBitwiseAnd:
        case EOpBitwiseXor:
        case EOpBitwiseOr:
        case EOpBitwiseAndAssign:
        case EOpBitwiseXorAssign:
        case EOpBitwiseOrAssign:
            // It is enough to check the type of only one operand, since later it
            // is checked that the operand types match.
            if (!IsInteger(left->getBasicType()))
            {
                return false;
            }
            break;
        default:
            break;
    }

    // Implicit type casting is not allowed in ESSL.
    if (!isBitShift && left->getBasicType() != right->getBasicType())
    {
        return false;
    }

    // Check that:
    // 1. Type sizes match exactly on ops that require that.
    // 2. Restrictions for structs that contain arrays or samplers are respected.
    // 3. Arithmetic op type dimensionality restrictions for ops other than multiply are respected.
    switch (op)
    {
        case EOpAssign:
        case EOpInitialize:
        case EOpEqual:
        case EOpNotEqual:
            // ESSL 1.00 sections 5.7, 5.8, 5.9
            if (mShaderVersion < 300 && left->getType().isStructureContainingArrays())
            {
                error(loc, "undefined operation for structs containing arrays",
                      GetOperatorString(op));
                return false;
            }
            // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
            // we interpret the spec so that this extends to structs containing samplers,
            // similarly to ESSL 1.00 spec.
            if (left->getType().isStructureContainingSamplers())
            {
                error(loc, "undefined operation for structs containing samplers",
                      GetOperatorString(op));
                return false;
            }

            if ((left->getNominalSize() != right->getNominalSize()) ||
                (left->getSecondarySize() != right->getSecondarySize()))
            {
                error(loc, "dimension mismatch", GetOperatorString(op));
                return false;
            }
            break;
        case EOpLessThan:
        case EOpGreaterThan:
        case EOpLessThanEqual:
        case EOpGreaterThanEqual:
            if (!left->isScalar() || !right->isScalar())
            {
                error(loc, "comparison operator only defined for scalars", GetOperatorString(op));
                return false;
            }
            if (left->getBasicType() == EbtBool || right->getBasicType() == EbtBool)
            {
                error(loc, "comparison operator not defined for booleans", GetOperatorString(op));
                return false;
            }
            break;
        case EOpAdd:
        case EOpSub:
        case EOpDiv:
        case EOpIMod:
        case EOpBitShiftLeft:
        case EOpBitShiftRight:
        case EOpBitwiseAnd:
        case EOpBitwiseXor:
        case EOpBitwiseOr:
        case EOpAddAssign:
        case EOpSubAssign:
        case EOpDivAssign:
        case EOpIModAssign:
        case EOpBitShiftLeftAssign:
        case EOpBitShiftRightAssign:
        case EOpBitwiseAndAssign:
        case EOpBitwiseXorAssign:
        case EOpBitwiseOrAssign:
            if ((left->isMatrix() && right->isVector()) || (left->isVector() && right->isMatrix()))
            {
                return false;
            }

            // Are the sizes compatible?
            if (left->getNominalSize() != right->getNominalSize() ||
                left->getSecondarySize() != right->getSecondarySize())
            {
                // If the nominal sizes of operands do not match:
                // One of them must be a scalar.
                if (!left->isScalar() && !right->isScalar())
                {
                    return false;
                }

                // In the case of compound assignment other than multiply-assign,
                // the right side needs to be a scalar. Otherwise a vector/matrix
                // would be assigned to a scalar. A scalar can't be shifted by a
                // vector either.
                if (!right->isScalar() &&
                    (IsAssignment(op) || op == EOpBitShiftLeft || op == EOpBitShiftRight))
                {
                    return false;
                }
            }
            break;
        default:
            break;
    }

    switch (op)
    {
        case EOpLogicalOr:
        case EOpLogicalXor:
        case EOpLogicalAnd:
            // Above operations are only supported on booleans
            ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
                   !right->getType().getStruct());
            if (left->getBasicType() != EbtBool || !left->isScalar() || !right->isScalar())
            {
                return false;
            }
            // Basic types matching should have been already checked.
            ASSERT(right->getBasicType() == EbtBool);
            break;
        case EOpAdd:
        case EOpAddAssign:
        case EOpSub:
        case EOpSubAssign:
        case EOpDiv:
        case EOpDivAssign:
        case EOpMul:
        case EOpMulAssign:
            // Above operations are not supported on booleans
            ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
                   !right->getType().getStruct());
            if (left->getBasicType() == EbtBool)
            {
                return false;
            }
            break;
        case EOpIMod:
        case EOpIModAssign:
            // Mod operator only supported on integers
            // Note that this is only for the % operator, not for mod()
            ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
                   !right->getType().getStruct());
            if (left->getBasicType() != EbtInt && left->getBasicType() != EbtUInt)
            {
                return false;
            }
            break;
        default:
            break;
    }

    return true;
}

bool TParseContext::isMultiplicationTypeCombinationValid(TOperator op,
                                                         const TType &left,
                                                         const TType &right)
{
    switch (op)
    {
        case EOpMul:
        case EOpMulAssign:
            return left.getNominalSize() == right.getNominalSize() &&
                   left.getSecondarySize() == right.getSecondarySize();
        case EOpVectorTimesScalar:
            return true;
        case EOpVectorTimesScalarAssign:
            ASSERT(!left.isMatrix() && !right.isMatrix());
            return left.isVector() && !right.isVector();
        case EOpVectorTimesMatrix:
            return left.getNominalSize() == right.getRows();
        case EOpVectorTimesMatrixAssign:
            ASSERT(!left.isMatrix() && right.isMatrix());
            return left.isVector() && left.getNominalSize() == right.getRows() &&
                   left.getNominalSize() == right.getCols();
        case EOpMatrixTimesVector:
            return left.getCols() == right.getNominalSize();
        case EOpMatrixTimesScalar:
            return true;
        case EOpMatrixTimesScalarAssign:
            ASSERT(left.isMatrix() && !right.isMatrix());
            return !right.isVector();
        case EOpMatrixTimesMatrix:
            return left.getCols() == right.getRows();
        case EOpMatrixTimesMatrixAssign:
            ASSERT(left.isMatrix() && right.isMatrix());
            // We need to check two things:
            // 1. The matrix multiplication step is valid.
            // 2. The result will have the same number of columns as the lvalue.
            return left.getCols() == right.getRows() && left.getCols() == right.getCols();

        default:
            UNREACHABLE();
            return false;
    }
}

TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
                                                   TIntermTyped *left,
                                                   TIntermTyped *right,
                                                   const TSourceLoc &loc)
{
    if (!binaryOpCommonCheck(op, left, right, loc))
    {
        return nullptr;
    }

    if (op == EOpMul)
    {
        op = TIntermBinary::GetMulOpBasedOnOperands(left->getType(), right->getType());
        if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
        {
            return nullptr;
        }
    }

    switch (op)
    {
        case EOpLogicalAnd:
            mIRBuilder.endShortCircuitAnd();
            break;
        case EOpLogicalOr:
            mIRBuilder.endShortCircuitOr();
            break;
        default:
            mIRBuilder.builtIn(op, 2);
            break;
    }

    TIntermBinary *node = new TIntermBinary(op, left, right);
    ASSERT(op != EOpAssign);
    markStaticUseIfSymbol(left);
    markStaticUseIfSymbol(right);
    node->setLine(loc);
    return expressionOrFoldedResult(node);
}

TIntermTyped *TParseContext::addBinaryMath(TOperator op,
                                           TIntermTyped *left,
                                           TIntermTyped *right,
                                           const TSourceLoc &loc)
{
    TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
    if (node == nullptr)
    {
        binaryOpError(loc, GetOperatorString(op), left->getType(), right->getType());
        return left;
    }
    return node;
}

TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op,
                                                        TIntermTyped *left,
                                                        TIntermTyped *right,
                                                        const TSourceLoc &loc)
{
    TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
    if (node == nullptr)
    {
        binaryOpError(loc, GetOperatorString(op), left->getType(), right->getType());
        node = CreateBoolNode(false);
        node->setLine(loc);
    }
    return node;
}

TIntermTyped *TParseContext::addAssign(TOperator op,
                                       TIntermTyped *left,
                                       TIntermTyped *right,
                                       const TSourceLoc &loc)
{
    checkCanBeLValue(loc, "assign", left);
    TIntermBinary *node = nullptr;
    if (binaryOpCommonCheck(op, left, right, loc))
    {
        TIntermBinary *lValue = left->getAsBinaryNode();
        if ((lValue != nullptr) &&
            (lValue->getOp() == EOpIndexIndirect || lValue->getOp() == EOpIndexDirect) &&
            IsTessellationControlShaderOutput(mShaderType, lValue->getLeft()->getQualifier()))
        {
            checkTCSOutVarIndexIsValid(lValue, loc);
        }

        if (op == EOpMulAssign)
        {
            op = TIntermBinary::GetMulAssignOpBasedOnOperands(left->getType(), right->getType());
            if (isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
            {
                node = new TIntermBinary(op, left, right);
            }
        }
        else
        {
            node = new TIntermBinary(op, left, right);
        }
    }
    if (node == nullptr)
    {
        assignError(loc, "assign", left->getType(), right->getType());
        return left;
    }

    if (op != EOpAssign)
    {
        markStaticUseIfSymbol(left);
    }
    mIRBuilder.builtIn(op, 2);

    markStaticUseIfSymbol(right);
    node->setLine(loc);
    return node;
}

void TParseContext::onShortCircuitAndBegin(TIntermTyped *left, const TSourceLoc &loc)
{
    if (!left->isScalar() || left->getBasicType() != EbtBool)
    {
        error(loc, "Left hand side of && must be a scalar bool", GetOperatorString(EOpLogicalAnd));
    }
    mIRBuilder.beginShortCircuitAnd();
}

void TParseContext::onShortCircuitOrBegin(TIntermTyped *left, const TSourceLoc &loc)
{
    if (!left->isScalar() || left->getBasicType() != EbtBool)
    {
        error(loc, "Left hand side of || must be a scalar bool", GetOperatorString(EOpLogicalOr));
    }
    mIRBuilder.beginShortCircuitOr();
}

void TParseContext::onCommaLeftHandSideParsed(TIntermTyped *left)
{
    if (left->getBasicType() != EbtVoid)
    {
        // The left-hand side's value is discarded, do so before the right-hand side is parsed (and
        // pushed to the stack).
        mIRBuilder.endStatementWithValue();
    }
}

TIntermTyped *TParseContext::addComma(TIntermTyped *left,
                                      TIntermTyped *right,
                                      const TSourceLoc &loc)
{
    // WebGL2 section 5.26, the following results in an error:
    // "Sequence operator applied to void, arrays, or structs containing arrays"
    if (mShaderSpec == SH_WEBGL2_SPEC &&
        (left->isArray() || left->getBasicType() == EbtVoid ||
         left->getType().isStructureContainingArrays() || right->isArray() ||
         right->getBasicType() == EbtVoid || right->getType().isStructureContainingArrays()))
    {
        error(loc,
              "sequence operator is not allowed for void, arrays, or structs containing arrays",
              ",");
    }
    if (left->isInterfaceBlock() || right->isInterfaceBlock())
    {
        error(loc, "sequence operator is not allowed for interface blocks", ",");
    }

    TIntermBinary *commaNode = TIntermBinary::CreateComma(left, right, mShaderVersion);
    markStaticUseIfSymbol(left);
    markStaticUseIfSymbol(right);
    commaNode->setLine(loc);

    return expressionOrFoldedResult(commaNode);
}

TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
{
    switch (op)
    {
        case EOpContinue:
            if (!isNestedIn(ControlFlowType::Loop))
            {
                error(loc, "continue statement only allowed in loops", "");
            }
            mIRBuilder.branchContinue();
            break;
        case EOpBreak:
            if (!isNestedIn(ControlFlowType::Loop) && !isNestedIn(ControlFlowType::Switch))
            {
                error(loc, "break statement only allowed in loops and switch statements", "");
            }
            else
            {
                mControlFlow.back().hasBreak = true;
            }
            mIRBuilder.branchBreak();
            break;
        case EOpReturn:
            if (mCurrentFunction->getReturnType().getBasicType() != EbtVoid)
            {
                error(loc, "non-void function must return a value", "return");
            }
            if (mDeclaringMain)
            {
                errorIfPLSDeclared(loc, PLSIllegalOperations::ReturnFromMain);
                mIsReturnVisitedInMain = true;
            }
            if (!mControlFlow.empty())
            {
                mControlFlow.back().hasReturn = true;
            }
            mIRBuilder.branchReturn();
            break;
        case EOpKill:
            if (mShaderType != GL_FRAGMENT_SHADER)
            {
                error(loc, "discard supported in fragment shaders only", "discard");
            }
            else
            {
                errorIfPLSDeclared(loc, PLSIllegalOperations::Discard);
            }
            mHasDiscard = true;
            mIRBuilder.branchDiscard();
            break;
        default:
            UNREACHABLE();
            break;
    }
    return addBranch(op, nullptr, loc);
}

TIntermBranch *TParseContext::addBranch(TOperator op,
                                        TIntermTyped *expression,
                                        const TSourceLoc &loc)
{
    if (expression != nullptr)
    {
        markStaticUseIfSymbol(expression);
        ASSERT(op == EOpReturn);
        mFunctionReturnsValue = true;
        if (mCurrentFunction->getReturnType().getBasicType() == EbtVoid)
        {
            error(loc, "void function cannot return a value", "return");
        }
        else if (mCurrentFunction->getReturnType() != expression->getType())
        {
            error(loc, "function return is not matching type:", "return");
        }
        if (!mControlFlow.empty())
        {
            mControlFlow.back().hasReturn = true;
        }
        mIRBuilder.branchReturnValue();
    }
    TIntermBranch *node = new TIntermBranch(op, expression);
    node->setLine(loc);
    return node;
}

void TParseContext::appendStatement(TIntermBlock *block, TIntermNode *statement)
{
    if (statement != nullptr)
    {
        // Validate that no statement is added before the first case label of a switch construct.
        if (statement->getAsCaseNode() == nullptr && isDirectlyUnderSwitch() &&
            mControlFlow.back().caseLabels.empty())
        {
            error(statement->getLine(), "statement before the first label", "switch");
        }

        markStaticUseIfSymbol(statement);
        block->appendStatement(statement);

        // Discard the value, if any.
        endStatementWithValue(statement);
    }
}

void TParseContext::checkTextureGather(TIntermAggregate *functionCall)
{
    const TOperator op    = functionCall->getOp();
    const TFunction *func = functionCall->getFunction();
    if (BuiltInGroup::IsTextureGather(op))
    {
        bool isTextureGatherOffsetOrOffsets =
            BuiltInGroup::IsTextureGatherOffset(op) || BuiltInGroup::IsTextureGatherOffsets(op);
        TIntermNode *componentNode = nullptr;
        TIntermSequence *arguments = functionCall->getSequence();
        ASSERT(arguments->size() >= 2u && arguments->size() <= 4u);
        const TIntermTyped *sampler = arguments->front()->getAsTyped();
        ASSERT(sampler != nullptr);
        switch (sampler->getBasicType())
        {
            case EbtSampler2D:
            case EbtISampler2D:
            case EbtUSampler2D:
            case EbtSampler2DArray:
            case EbtISampler2DArray:
            case EbtUSampler2DArray:
                if ((!isTextureGatherOffsetOrOffsets && arguments->size() == 3u) ||
                    (isTextureGatherOffsetOrOffsets && arguments->size() == 4u))
                {
                    componentNode = arguments->back();
                }
                break;
            case EbtSamplerCube:
            case EbtISamplerCube:
            case EbtUSamplerCube:
            case EbtSamplerCubeArray:
            case EbtISamplerCubeArray:
            case EbtUSamplerCubeArray:
                ASSERT(!isTextureGatherOffsetOrOffsets);
                if (arguments->size() == 3u)
                {
                    componentNode = arguments->back();
                }
                break;
            case EbtSampler2DShadow:
            case EbtSampler2DArrayShadow:
            case EbtSamplerCubeShadow:
            case EbtSamplerCubeArrayShadow:
                break;
            default:
                UNREACHABLE();
                break;
        }
        if (componentNode)
        {
            const TIntermConstantUnion *componentConstantUnion =
                componentNode->getAsConstantUnion();
            if (componentNode->getAsTyped()->getQualifier() != EvqConst || !componentConstantUnion)
            {
                error(functionCall->getLine(), "Texture component must be a constant expression",
                      func->name());
            }
            else
            {
                int component = componentConstantUnion->getIConst(0);
                if (component < 0 || component > 3)
                {
                    error(functionCall->getLine(), "Component must be in the range [0;3]",
                          func->name());
                }
            }
        }
    }
}

void TParseContext::checkTextureOffset(TIntermAggregate *functionCall)
{
    const TOperator op         = functionCall->getOp();
    const TFunction *func      = functionCall->getFunction();
    TIntermNode *offset        = nullptr;
    TIntermSequence *arguments = functionCall->getSequence();

    if (BuiltInGroup::IsTextureOffsetNoBias(op) || BuiltInGroup::IsTextureGatherOffsetNoComp(op) ||
        BuiltInGroup::IsTextureGatherOffsetRef(op) ||
        BuiltInGroup::IsTextureGatherOffsetsNoComp(op) ||
        BuiltInGroup::IsTextureGatherOffsetsRef(op))
    {
        offset = arguments->back();
    }
    else if (BuiltInGroup::IsTextureOffsetBias(op) || BuiltInGroup::IsTextureGatherOffsetComp(op) ||
             BuiltInGroup::IsTextureGatherOffsetsComp(op))
    {
        // A bias or comp parameter follows the offset parameter.
        ASSERT(arguments->size() >= 3);
        offset = (*arguments)[2];
    }

    // If not one of the above built-ins, there's nothing to do here.
    if (offset == nullptr)
    {
        return;
    }

    bool isTextureGatherOffset             = BuiltInGroup::IsTextureGatherOffset(op);
    bool isTextureGatherOffsets            = BuiltInGroup::IsTextureGatherOffsets(op);
    bool useTextureGatherOffsetConstraints = isTextureGatherOffset || isTextureGatherOffsets;

    int minOffsetValue = useTextureGatherOffsetConstraints
                             ? mResources.MinProgramTextureGatherOffset
                             : mResources.MinProgramTexelOffset;
    int maxOffsetValue = useTextureGatherOffsetConstraints
                             ? mResources.MaxProgramTextureGatherOffset
                             : mResources.MaxProgramTexelOffset;

    if (isTextureGatherOffsets)
    {
        // If textureGatherOffsets, the offsets parameter is an array, which is expected as an
        // aggregate constructor node or as a symbol node with a constant value.
        TIntermAggregate *offsetAggregate = offset->getAsAggregate();
        TIntermSymbol *offsetSymbol       = offset->getAsSymbolNode();

        const TConstantUnion *offsetValues = offsetAggregate ? offsetAggregate->getConstantValue()
                                             : offsetSymbol  ? offsetSymbol->getConstantValue()
                                                             : nullptr;

        if (offsetValues == nullptr)
        {
            error(functionCall->getLine(), "Texture offsets must be a constant expression",
                  func->name());
            return;
        }

        constexpr unsigned int kOffsetsCount = 4;
        const TType &offsetType =
            offsetAggregate != nullptr ? offsetAggregate->getType() : offsetSymbol->getType();
        if (offsetType.getNumArraySizes() != 1 || offsetType.getArraySizes()[0] != kOffsetsCount)
        {
            error(functionCall->getLine(), "Texture offsets must be an array of 4 elements",
                  func->name());
            return;
        }

        size_t size = offsetType.getObjectSize() / kOffsetsCount;
        for (unsigned int i = 0; i < kOffsetsCount; ++i)
        {
            ANGLE_UNSAFE_TODO(checkSingleTextureOffset(offset->getLine(), &offsetValues[i * size],
                                                       size, minOffsetValue, maxOffsetValue));
        }
    }
    else
    {
        // If textureOffset or textureGatherOffset, the offset is expected to be found as a constant
        // union.
        TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();

        // ES3.2 or ES3.1's EXT_gpu_shader5 allow non-const offsets to be passed to
        // textureGatherOffset.
        bool textureGatherOffsetMustBeConst = mShaderVersion <= 310 &&
                                              !isExtensionEnabled(TExtension::EXT_gpu_shader5) &&
                                              !isExtensionEnabled(TExtension::OES_gpu_shader5);

        bool isOffsetConst =
            offset->getAsTyped()->getQualifier() == EvqConst && offsetConstantUnion != nullptr;
        bool offsetMustBeConst = !isTextureGatherOffset || textureGatherOffsetMustBeConst;

        if (!isOffsetConst && offsetMustBeConst)
        {
            error(functionCall->getLine(), "Texture offset must be a constant expression",
                  func->name());
            return;
        }

        // We cannot verify non-constant offsets to textureGatherOffset.
        if (offsetConstantUnion == nullptr)
        {
            ASSERT(!offsetMustBeConst);
            return;
        }

        size_t size                  = offsetConstantUnion->getType().getObjectSize();
        const TConstantUnion *values = offsetConstantUnion->getConstantValue();
        checkSingleTextureOffset(offset->getLine(), values, size, minOffsetValue, maxOffsetValue);
    }
}

void TParseContext::checkSingleTextureOffset(const TSourceLoc &line,
                                             const TConstantUnion *values,
                                             size_t size,
                                             int minOffsetValue,
                                             int maxOffsetValue)
{
    for (size_t i = 0u; i < size; ++i)
    {
        ANGLE_UNSAFE_TODO(ASSERT(values[i].getType() == EbtInt));
        int offsetValue = ANGLE_UNSAFE_TODO(values[i].getIConst());
        if (offsetValue > maxOffsetValue || offsetValue < minOffsetValue)
        {
            std::stringstream tokenStream = sh::InitializeStream<std::stringstream>();
            tokenStream << offsetValue;
            std::string token = tokenStream.str();
            error(line, "Texture offset value out of valid range", token.c_str());
        }
    }
}

void TParseContext::checkInterpolationFS(TIntermAggregate *functionCall)
{
    const TFunction *func = functionCall->getFunction();
    if (!BuiltInGroup::IsInterpolationFS(functionCall->getOp()))
    {
        return;
    }

    TIntermTyped *arg0 = nullptr;

    if (functionCall->getAsAggregate())
    {
        const TIntermSequence *argp = functionCall->getSequence();
        if (argp->size() > 0)
        {
            arg0 = (*argp)[0]->getAsTyped();
        }
    }
    else
    {
        assert(functionCall->getAsUnaryNode());
        arg0 = functionCall->getAsUnaryNode()->getOperand();
    }

    // Make sure the first argument is an interpolant, or an array element of an interpolant
    if (!IsVaryingIn(arg0->getType().getQualifier()))
    {
        // It might still be an array element.
        const TIntermTyped *base = FindLValueBase(arg0);

        if (base == nullptr || (!IsVaryingIn(base->getType().getQualifier())))
        {
            error(arg0->getLine(),
                  "first argument must be an interpolant, or interpolant-array element",
                  func->name());
        }
    }
}

void TParseContext::checkAtomicMemoryBuiltinFunctions(TIntermAggregate *functionCall)
{
    const TFunction *func = functionCall->getFunction();
    if (BuiltInGroup::IsAtomicMemory(functionCall->getOp()))
    {
        TIntermSequence *arguments = functionCall->getSequence();
        TIntermTyped *memNode      = (*arguments)[0]->getAsTyped();

        if (IsBufferOrSharedVariable(memNode))
        {
            return;
        }

        while (memNode->getAsBinaryNode() || memNode->getAsSwizzleNode())
        {
            // Child 0 is "left" if binary, and the expression being swizzled if swizzle.
            // Note: we don't need to check that the binary operation is one of EOp*Index*, as any
            // other operation will result in a temp value which cannot be passed to this
            // out/inout parameter anyway.
            memNode = memNode->getChildNode(0)->getAsTyped();
            if (IsBufferOrSharedVariable(memNode))
            {
                return;
            }
        }

        error(memNode->getLine(),
              "The value passed to the mem argument of an atomic memory function does not "
              "correspond to a buffer or shared variable.",
              func->name());
    }
}

// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall)
{
    const TOperator op = functionCall->getOp();

    if (BuiltInGroup::IsImage(op))
    {
        TIntermSequence *arguments = functionCall->getSequence();
        TIntermTyped *imageNode    = (*arguments)[0]->getAsTyped();

        const TMemoryQualifier &memoryQualifier = imageNode->getMemoryQualifier();

        if (BuiltInGroup::IsImageStore(op))
        {
            if (memoryQualifier.readonly)
            {
                error(imageNode->getLine(),
                      "'imageStore' cannot be used with images qualified as 'readonly'",
                      GetImageArgumentToken(imageNode));
            }
        }
        else if (BuiltInGroup::IsImageLoad(op))
        {
            if (memoryQualifier.writeonly)
            {
                error(imageNode->getLine(),
                      "'imageLoad' cannot be used with images qualified as 'writeonly'",
                      GetImageArgumentToken(imageNode));
            }
        }
        else if (BuiltInGroup::IsImageAtomic(op))
        {
            if (memoryQualifier.readonly)
            {
                error(imageNode->getLine(),
                      "'imageAtomic' cannot be used with images qualified as 'readonly'",
                      GetImageArgumentToken(imageNode));
            }
            if (memoryQualifier.writeonly)
            {
                error(imageNode->getLine(),
                      "'imageAtomic' cannot be used with images qualified as 'writeonly'",
                      GetImageArgumentToken(imageNode));
            }
        }
    }
}

// GLSL ES 3.10 Revision 4, 13.51 Matching of Memory Qualifiers in Function Parameters
void TParseContext::checkImageMemoryAccessForUserDefinedFunctions(
    const TFunction *functionDefinition,
    const TIntermAggregate *functionCall)
{
    ASSERT(functionCall->getOp() == EOpCallFunctionInAST);

    const TIntermSequence &arguments = *functionCall->getSequence();

    ASSERT(functionDefinition->getParamCount() == arguments.size());

    for (size_t i = 0; i < arguments.size(); ++i)
    {
        TIntermTyped *typedArgument        = arguments[i]->getAsTyped();
        const TType &functionArgumentType  = typedArgument->getType();
        const TType &functionParameterType = functionDefinition->getParam(i)->getType();
        ASSERT(functionArgumentType.getBasicType() == functionParameterType.getBasicType());

        if (IsImage(functionArgumentType.getBasicType()))
        {
            const TMemoryQualifier &functionArgumentMemoryQualifier =
                functionArgumentType.getMemoryQualifier();
            const TMemoryQualifier &functionParameterMemoryQualifier =
                functionParameterType.getMemoryQualifier();
            if (functionArgumentMemoryQualifier.readonly &&
                !functionParameterMemoryQualifier.readonly)
            {
                error(functionCall->getLine(),
                      "Function call discards the 'readonly' qualifier from image",
                      GetImageArgumentToken(typedArgument));
            }

            if (functionArgumentMemoryQualifier.writeonly &&
                !functionParameterMemoryQualifier.writeonly)
            {
                error(functionCall->getLine(),
                      "Function call discards the 'writeonly' qualifier from image",
                      GetImageArgumentToken(typedArgument));
            }

            if (functionArgumentMemoryQualifier.coherent &&
                !functionParameterMemoryQualifier.coherent)
            {
                error(functionCall->getLine(),
                      "Function call discards the 'coherent' qualifier from image",
                      GetImageArgumentToken(typedArgument));
            }

            if (functionArgumentMemoryQualifier.volatileQualifier &&
                !functionParameterMemoryQualifier.volatileQualifier)
            {
                error(functionCall->getLine(),
                      "Function call discards the 'volatile' qualifier from image",
                      GetImageArgumentToken(typedArgument));
            }
        }
    }
}

TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunctionLookup *fnCall, const TSourceLoc &loc)
{
    if (fnCall->thisNode() != nullptr)
    {
        return addMethod(fnCall, loc);
    }
    if (fnCall->isConstructor())
    {
        return addConstructor(fnCall, loc);
    }
    return addNonConstructorFunctionCall(fnCall, loc);
}

TIntermTyped *TParseContext::addMethod(TFunctionLookup *fnCall, const TSourceLoc &loc)
{
    TIntermTyped *thisNode = fnCall->thisNode();
    // It's possible for the name pointer in the TFunction to be null in case it gets parsed as
    // a constructor. But such a TFunction can't reach here, since the lexer goes into FIELDS
    // mode after a dot, which makes type identifiers to be parsed as FIELD_SELECTION instead.
    // So accessing fnCall->name() below is safe.
    if (fnCall->name() != "length")
    {
        error(loc, "invalid method", fnCall->name());
    }
    else if (!fnCall->arguments().empty())
    {
        error(loc, "method takes no parameters", "length");
    }
    else if (!thisNode->isArray())
    {
        error(loc, "length can only be called on arrays", "length");
    }
    else if (thisNode->getQualifier() == EvqPerVertexIn &&
             mGeometryShaderInputPrimitiveType == EptUndefined)
    {
        ASSERT(mShaderType == GL_GEOMETRY_SHADER_EXT);
        error(loc, "missing input primitive declaration before calling length on gl_in", "length");
    }
    else
    {
        switch (thisNode->getQualifier())
        {
            case EvqClipDistance:
                MarkClipCullArrayLengthMethodCall(loc, &mClipDistanceInfo);
                break;
            case EvqCullDistance:
                MarkClipCullArrayLengthMethodCall(loc, &mCullDistanceInfo);
                break;
            default:
                break;
        }

        mIRBuilder.arrayLength();

        TIntermUnary *node = new TIntermUnary(EOpArrayLength, thisNode, nullptr);
        markStaticUseIfSymbol(thisNode);
        node->setLine(loc);
        return node->fold(mDiagnostics);
    }
    return CreateZeroNode(TType(EbtInt, EbpUndefined, EvqConst));
}

TIntermTyped *TParseContext::addNonConstructorFunctionCallImpl(TFunctionLookup *fnCall,
                                                               const TSourceLoc &loc)
{
    // First check whether the function has been hidden by a variable name or struct typename by
    // using the symbol looked up in the lexical phase. If the function is not hidden, look for one
    // with a matching argument list.
    if (fnCall->symbol() != nullptr && !fnCall->symbol()->isFunction())
    {
        error(loc, "function name expected", fnCall->name());
    }
    else
    {
        // There are no inner functions, so it's enough to look for user-defined functions in the
        // global scope.
        const TSymbol *symbol = symbolTable.findGlobal(fnCall->getMangledName());

        if (symbol != nullptr)
        {
            // A user-defined function - could be an overloaded built-in as well.
            ASSERT(symbol->symbolType() == SymbolType::UserDefined);
            const TFunction *fnCandidate = static_cast<const TFunction *>(symbol);
            TIntermAggregate *callNode =
                TIntermAggregate::CreateFunctionCall(*fnCandidate, &fnCall->arguments());
            callNode->setLine(loc);
            checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode);
            functionCallRValueLValueErrorCheck(fnCandidate, callNode);

            mCallGraph[mCurrentFunction].insert(fnCandidate);
            mIRBuilder.callFunction(mFunctionToId.at(fnCandidate));
            return callNode;
        }

        symbol = symbolTable.findBuiltIn(fnCall->getMangledName(), mShaderVersion);

        if (symbol != nullptr)
        {
            // A built-in function.
            ASSERT(symbol->symbolType() == SymbolType::BuiltIn);
            const TFunction *fnCandidate = static_cast<const TFunction *>(symbol);

            if (!fnCandidate->extensions().empty() &&
                fnCandidate->extensions()[0] != TExtension::UNDEFINED)
            {
                checkCanUseOneOfExtensions(loc, fnCandidate->extensions());
            }

            // From GLES 3.2:
            //
            // For tessellation control shaders, the barrier() function may only be placed inside
            // the function main() of the shader and may not be called within any control flow.
            // Barriers are also disallowed after a return statement in the function main().
            if (fnCandidate->getBuiltInOp() == EOpBarrierTCS)
            {
                if (mIsReturnVisitedInMain)
                {
                    error(loc,
                          "barrier() may not be called at any point after a return statement in "
                          "the function main()",
                          "barrier");
                }
                else if (!mDeclaringMain)
                {
                    error(loc, "barrier() is only allowed inside the function main()", "barrier");
                }
                else if (!mControlFlow.empty())
                {
                    error(loc, "barrier() is not allowed within any control flow", "barrier");
                }
            }

            // All function calls are mapped to a built-in operation.
            TOperator op = fnCandidate->getBuiltInOp();
            if (BuiltInGroup::IsMath(op) && fnCandidate->getParamCount() == 1)
            {
                // Treat it like a built-in unary operator.
                TIntermNode *unaryParamNode = fnCall->arguments().front();
                return createUnaryMath(op, unaryParamNode->getAsTyped(), loc, fnCandidate);
            }

            TIntermAggregate *callNode =
                TIntermAggregate::CreateBuiltInFunctionCall(*fnCandidate, &fnCall->arguments());
            callNode->setLine(loc);

            if (UsesDerivatives(callNode))
            {
                mUsesDerivatives = true;
            }

            checkAtomicMemoryBuiltinFunctions(callNode);
            checkTextureOffset(callNode);
            checkTextureGather(callNode);
            checkInterpolationFS(callNode);
            checkImageMemoryAccessForBuiltinFunctions(callNode);

            // Some built-in functions have out parameters too.
            functionCallRValueLValueErrorCheck(fnCandidate, callNode);

            mIRBuilder.builtIn(op, fnCandidate->getParamCount());

            // See if we can constant fold a built-in. Note that this may be possible
            // even if it is not const-qualified.
            return callNode->fold(mDiagnostics);
        }
        else
        {
            error(loc, "no matching overloaded function found", fnCall->name());
        }
    }
    return nullptr;
}

TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunctionLookup *fnCall,
                                                           const TSourceLoc &loc)
{
    TIntermTyped *result = addNonConstructorFunctionCallImpl(fnCall, loc);
    if (result != nullptr)
    {
        return result;
    }
    // Error message was already written. Put on an unused node for error recovery.
    return CreateZeroNode(TType(EbtFloat, EbpMedium, EvqConst));
}

void TParseContext::onTernaryConditionParsed(TIntermTyped *cond, const TSourceLoc &line)
{
    checkIsScalarBool(line, cond);
    mIRBuilder.beginTernaryTrueExpression();
}

void TParseContext::onTernaryTrueExpressionParsed(TIntermTyped *trueExpression,
                                                  const TSourceLoc &line)
{
    mIRBuilder.endTernaryTrueExpression(trueExpression->getBasicType());
    mIRBuilder.beginTernaryFalseExpression();
}

TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
                                                 TIntermTyped *trueExpression,
                                                 TIntermTyped *falseExpression,
                                                 const TSourceLoc &loc)
{
    if (!checkIsScalarBool(loc, cond))
    {
        return falseExpression;
    }

    if (trueExpression->getType() != falseExpression->getType())
    {
        TInfoSinkBase reasonStream;
        reasonStream << "mismatching ternary operator operand types '" << trueExpression->getType()
                     << " and '" << falseExpression->getType() << "'";
        error(loc, reasonStream.c_str(), "?:");
        return falseExpression;
    }
    const TBasicType basicType = trueExpression->getBasicType();
    if (IsOpaqueType(basicType) || trueExpression->getType().isStructureContainingSamplers())
    {
        // ESSL 1.00 section 4.1.7
        // ESSL 3.00.6 section 4.1.7
        // Opaque/sampler types are not allowed in the ternary operator, including structs with
        // samplers in them.
        error(loc, "ternary operator is not allowed for opaque types", "?:");
        return falseExpression;
    }

    if (cond->getMemoryQualifier().writeonly || trueExpression->getMemoryQualifier().writeonly ||
        falseExpression->getMemoryQualifier().writeonly)
    {
        error(loc, "ternary operator is not allowed for variables with writeonly", "?:");
        return falseExpression;
    }

    // ESSL 1.00.17 sections 5.2 and 5.7:
    // Ternary operator is not among the operators allowed for structures/arrays.
    // ESSL 3.00 and ESSL 3.10 section 5.7:
    // Ternary operator supports structs, but array support is optional for arrays.
    // ESSL 3.20 section 5.7:
    // Ternary operator supports structs and arrays unconditionally.
    // In WebGL2 section 5.26, ternary is banned for both arrays and structs.
    if ((mShaderVersion < 300 || mShaderSpec == SH_WEBGL2_SPEC) && trueExpression->isArray())
    {
        error(loc, "ternary operator is not allowed for arrays in ESSL 1.0 and webgl", "?:");
        return falseExpression;
    }
    if ((mShaderVersion < 300 || mShaderSpec == SH_WEBGL2_SPEC) && basicType == EbtStruct)
    {
        error(loc, "ternary operator is not allowed for structures in ESSL 1.0 and webgl", "?:");
        return falseExpression;
    }
    if (basicType == EbtInterfaceBlock)
    {
        error(loc, "ternary operator is not allowed for interface blocks", "?:");
        return falseExpression;
    }

    // WebGL2 section 5.26, the following results in an error:
    // "Ternary operator applied to void, arrays, or structs containing arrays"
    if (mShaderSpec == SH_WEBGL2_SPEC && basicType == EbtVoid)
    {
        error(loc, "ternary operator is not allowed for void", "?:");
        return falseExpression;
    }

    mIRBuilder.endTernaryFalseExpression(basicType);
    mIRBuilder.endTernary(basicType);

    TIntermTernary *node = new TIntermTernary(cond, trueExpression, falseExpression);
    markStaticUseIfSymbol(cond);
    markStaticUseIfSymbol(trueExpression);
    markStaticUseIfSymbol(falseExpression);
    node->setLine(loc);
    return expressionOrFoldedResult(node);
}

ir::TypeId TParseContext::getTypeId(const TType &type)
{
    if (type.isTypeIdSet())
    {
        return type.typeId();
    }

    // Normally, type ids are generated at the same time as types are, except for built-ins where
    // the type is baked in.  For now, calculate the type ID.
    const TSymbol *block     = nullptr;
    const TFieldList *fields = nullptr;
    ir::TypeId id;
    if (type.getStruct())
    {
        block  = type.getStruct();
        fields = &type.getStruct()->fields();
    }
    else if (type.getInterfaceBlock())
    {
        block  = type.getInterfaceBlock();
        fields = &type.getInterfaceBlock()->fields();
    }

    if (block)
    {
        if (mSymbolToTypeId.find(block) != mSymbolToTypeId.end())
        {
            id = mSymbolToTypeId.at(block);
        }
        else
        {
            TVector<ir::TypeId> fieldTypeIds;
            for (const TField *field : *fields)
            {
                fieldTypeIds.push_back(getTypeId(*field->type()));
            }

            // Same issue with built-ins where the type id is not baked in.  So the type id of each
            // field is also calculated here and passed in.
            id                     = ANGLE_UNSAFE_TODO(mIRBuilder.getStructTypeId(
                block->symbolType() == SymbolType::Empty ? kEmptyImmutableString : block->name(),
                angle::Span<const TField *const>(fields->data(), fields->size()),
                angle::Span<ir::TypeId>(fieldTypeIds.data(), fieldTypeIds.size()),
                block->isInterfaceBlock(), block->symbolType() == SymbolType::BuiltIn, true));
            mSymbolToTypeId[block] = id;
        }
    }
    else
    {
        id = mIRBuilder.getBasicTypeId(type.getBasicType(), type.getNominalSize(),
                                       type.getSecondarySize());
    }

    if (type.isArray())
    {
        // Make sure array types that are yet to be sized are not added to the IR yet.
        ASSERT(std::find(mDeferredArrayTypesToSize.begin(), mDeferredArrayTypesToSize.end(),
                         &type) == mDeferredArrayTypesToSize.end());
        id = mIRBuilder.getArrayTypeId(id, type.getArraySizes());
    }

    return id;
}

void TParseContext::pushVariable(const TVariable *variable)
{
    if (mDiagnostics->numErrors() > 0)
    {
        return;
    }

    const VariableToIdInfo &info = mVariableToId.at(variable);
    mIRBuilder.pushVariable(info.id);
    if (info.implicitField != VariableToIdInfo::kNoImplicitField)
    {
        mIRBuilder.structField(info.implicitField);
    }
}

const TConstantUnion *TParseContext::pushConstant(const TConstantUnion *constant, const TType &type)
{
    const ir::TypeId typeId = getTypeId(type);
    if (type.isArray())
    {
        TType elementType(type);
        elementType.toArrayElementType();

        const size_t arraySize = type.getOutermostArraySize();
        for (size_t i = 0; i < arraySize; ++i)
        {
            constant = pushConstant(constant, elementType);
        }
        mIRBuilder.construct(typeId, arraySize);
    }
    else if (type.getBasicType() == EbtStruct)
    {
        const TStructure *structure = type.getStruct();

        for (const TField *field : structure->fields())
        {
            const TType *fieldType = field->type();
            constant               = pushConstant(constant, *fieldType);
        }
        mIRBuilder.construct(typeId, structure->fields().size());
    }
    else
    {
        size_t size = type.getObjectSize();
        for (size_t i = 0; i < size; ++i, ANGLE_UNSAFE_TODO(++constant))
        {
            switch (constant->getType())
            {
                case EbtFloat:
                    mIRBuilder.pushConstantFloat(constant->getFConst());
                    break;
                case EbtInt:
                    mIRBuilder.pushConstantInt(constant->getIConst());
                    break;
                case EbtUInt:
                    mIRBuilder.pushConstantUint(constant->getUConst());
                    break;
                case EbtBool:
                    mIRBuilder.pushConstantBool(constant->getBConst());
                    break;
                case EbtYuvCscStandardEXT:
                    mIRBuilder.pushConstantYuvCscStandard(constant->getYuvCscStandardEXTConst());
                    break;
                default:
                    UNREACHABLE();
            }
        }
        if (size > 1)
        {
            mIRBuilder.construct(typeId, size);
        }
    }

    return constant;
}

void TParseContext::endStatementWithValue(TIntermNode *statement)
{
    TIntermTyped *typed = statement ? statement->getAsTyped() : nullptr;
    if (typed && typed->getBasicType() != EbtVoid)
    {
        mIRBuilder.endStatementWithValue();
    }
}

void TParseContext::prependPendingStructDeclarations()
{
    TIntermSequence allStructDecls;

    // Do the following for all structs:
    //
    // * First, modify the name of the struct.  This breaks the symbol table, as names cannot be
    //   looked up anymore, but that's ok because this is the end of parse and no transformation
    //   looks up user symbol names anymore.  The struct names are used during link to match
    //   uniforms, and so for global structs, the name is suffixed by |_0| to be identical between
    //   shader stages.  For function-local structs it's suffixed by |_uniqueId|
    // * Then, create a global declarator for the struct and append it to the list of declarations.
    //
    // The whole list is prepended to the shader at the end.  Global structs are declared first, as
    // they may be used by function-local structs.  Within global or function-local structs, they
    // are declared in the order they are encountered in the shader for the same reason.

    for (TStructure *structure : mGlobalNamedStructs)
    {
        allStructDecls.push_back(
            RenameAndDeclareStruct(&symbolTable, structure, StructureOriginalScope::Global));
    }

    for (TStructure *structure : mFunctionLocalNamedStructs)
    {
        allStructDecls.push_back(
            RenameAndDeclareStruct(&symbolTable, structure, StructureOriginalScope::FunctionLocal));
    }

    mTreeRoot->getSequence()->insert(mTreeRoot->getSequence()->begin(), allStructDecls.begin(),
                                     allStructDecls.end());
}

void TParseContext::checkCallGraph()
{
    // Verify that the call graph does not contain a loop.
    enum class VisitState
    {
        NotVisited,
        Visiting,
        Visited,
    };
    struct Visit
    {
        // Note: Can't use default initializer because of msvc.
        Visit() : state(VisitState::NotVisited) {}
        VisitState state;
        uint32_t callDepth = 0;
    };
    TUnorderedMap<const TFunction *, Visit> visitState;

    TVector<const TFunction *> visitStack;
    visitStack.reserve(mCallGraph.size());

    // Visit all the functions; even if a function is unreachable, it must still result in a compile
    // error.
    for (auto iter : mCallGraph)
    {
        visitStack.push_back(iter.first);

        // Check the callees of this function too, if any is undefined, it's an error.
        for (const TFunction *callee : iter.second)
        {
            if (mDefinedFunctions.find(callee) == mDefinedFunctions.end())
            {
                std::stringstream errorStream = sh::InitializeStream<std::stringstream>();
                errorStream << "Function " << callee->name() << "() called by "
                            << iter.first->name() << "() is undefined";
                mDiagnostics->globalError(errorStream.str().c_str());
            }
        }
    }

    auto checkRecursion = [this, &visitState, &visitStack](const TFunction *function,
                                                           const TFunction *callee) -> bool {
        if (visitState[callee].state == VisitState::Visiting)
        {
            std::stringstream errorStream = sh::InitializeStream<std::stringstream>();
            errorStream << "Recursive function call in the following call chain: "
                        << callee->name();
            if (callee != function)
            {
                for (auto caller = visitStack.rbegin(); caller != visitStack.rend(); ++caller)
                {
                    if (visitState[*caller].state != VisitState::Visiting)
                    {
                        continue;
                    }

                    errorStream << " <- " << (*caller)->name();
                    if (*caller == callee)
                    {
                        break;
                    }
                }
            }
            mDiagnostics->globalError(errorStream.str().c_str());
            visitState[callee].state = VisitState::Visited;
            return false;
        }
        return true;
    };

    auto postVisitCheckCallDepth = [this, &visitState](const TFunction *function) -> bool {
        if (!mCompileOptions.limitCallStackDepth)
        {
            return true;
        }

        uint32_t callDepth = 0;
        for (const TFunction *callee : mCallGraph[function])
        {
            callDepth = std::max(callDepth, visitState[callee].callDepth);
        }
        // Add one depth for the call from this function to the callees.
        ++callDepth;

        visitState[function].callDepth = callDepth;

        if (callDepth > static_cast<uint32_t>(mResources.MaxCallStackDepth))
        {
            std::stringstream errorStream = sh::InitializeStream<std::stringstream>();
            errorStream << "Call stack too deep (larger than " << mResources.MaxCallStackDepth
                        << ") in function: " << function->name();
            mDiagnostics->globalError(errorStream.str().c_str());
            return false;
        }

        return true;
    };

    while (!visitStack.empty())
    {
        const TFunction *function = visitStack.back();
        visitStack.pop_back();

        Visit &visit = visitState[function];

        // If node is already visited, ignore it as it's already checked.
        if (visit.state == VisitState::Visited)
        {
            continue;
        }
        // If the node is done being visited, mark it so.
        if (visit.state == VisitState::Visiting)
        {
            visit.state = VisitState::Visited;
            if (!postVisitCheckCallDepth(function))
            {
                break;
            }
            continue;
        }

        // Add the callees to the stack.
        visit.state = VisitState::Visiting;
        visitStack.push_back(function);

        for (const TFunction *callee : mCallGraph[function])
        {
            // If any is being visited, that's a recursion!
            if (!checkRecursion(function, callee))
            {
                break;
            }

            visitStack.push_back(callee);
        }
    }
}

void TParseContext::postParseValidateFragmentOutputLocations()
{
    TVector<VariableAndLocation> validOutputs(mFragmentOutputIndex1Used
                                                  ? mResources.MaxDualSourceDrawBuffers
                                                  : mResources.MaxDrawBuffers);
    TVector<VariableAndLocation> validSecondaryOutputs(mResources.MaxDualSourceDrawBuffers);

    for (const VariableAndLocation &variable : mFragmentOutputsWithLocation)
    {
        const TType &type = variable.variable->getType();
        ASSERT(!type.isArrayOfArrays());  // Disallowed in GLSL ES 3.10 section 4.3.6.
        const size_t elementCount =
            static_cast<size_t>(type.isArray() ? type.getOutermostArraySize() : 1u);
        const size_t location = static_cast<size_t>(type.getLayoutQualifier().location);

        ASSERT(type.getLayoutQualifier().location != -1);

        TVector<VariableAndLocation> *validOutputsToUse = &validOutputs;
        TVector<VariableAndLocation> *otherOutputsToUse = &validSecondaryOutputs;
        // The default index is 0, so we only assign the output to secondary outputs in case the
        // index is explicitly set to 1.
        if (type.getLayoutQualifier().index == 1)
        {
            validOutputsToUse = &validSecondaryOutputs;
            otherOutputsToUse = &validOutputs;
        }

        if (location + elementCount <= validOutputsToUse->size())
        {
            for (size_t elementIndex = 0; elementIndex < elementCount; elementIndex++)
            {
                const size_t offsetLocation = location + elementIndex;
                if ((*validOutputsToUse)[offsetLocation].variable != nullptr)
                {
                    std::stringstream strstr = sh::InitializeStream<std::stringstream>();
                    strstr << "conflicting output locations with previously defined output '"
                           << (*validOutputsToUse)[offsetLocation].variable->name() << "'";
                    error(variable.line, strstr.str().c_str(), variable.variable->name());
                }
                else
                {
                    (*validOutputsToUse)[offsetLocation] = variable;
                    if (offsetLocation < otherOutputsToUse->size())
                    {
                        VariableAndLocation other = (*otherOutputsToUse)[offsetLocation];
                        if (other.variable != nullptr &&
                            other.variable->getType().getBasicType() != type.getBasicType())
                        {
                            std::stringstream strstr = sh::InitializeStream<std::stringstream>();
                            strstr << "conflicting output types with previously defined output '"
                                   << other.variable->name() << "' for location " << offsetLocation;
                            error(variable.line, strstr.str().c_str(), variable.variable->name());
                        }
                    }
                }
            }
        }
        else if (elementCount > 0)
        {
            std::stringstream strstr = sh::InitializeStream<std::stringstream>();
            strstr << (elementCount > 1 ? "output array locations would exceed "
                                        : "output location must be < ")
                   << "MAX_" << (mFragmentOutputIndex1Used ? "DUAL_SOURCE_" : "") << "DRAW_BUFFERS";
            error(variable.line, strstr.str().c_str(), variable.variable->name());
        }
    }

    // For outputs without a location, one may be provided with glBindFragDataLocationEXT or
    // glBindFragDataLocationIndexedEXT, so we can't validate conflicts until link time.  However,
    // we _can_ validate that no single array is larger than MAX_DRAW_BUFFERS.
    for (const VariableAndLocation &variable : mFragmentOutputsWithoutLocation)
    {
        const TType &type = variable.variable->getType();
        ASSERT(!type.isArrayOfArrays());  // Disallowed in GLSL ES 3.10 section 4.3.6.
        const size_t elementCount =
            static_cast<size_t>(type.isArray() ? type.getOutermostArraySize() : 1u);
        if (elementCount > validOutputs.size())
        {
            std::stringstream strstr = sh::InitializeStream<std::stringstream>();
            strstr << "output array locations would exceed "
                   << "MAX_" << (mFragmentOutputIndex1Used ? "DUAL_SOURCE_" : "") << "DRAW_BUFFERS";
            error(variable.line, strstr.str().c_str(), variable.variable->name());
        }
    }

    const bool isWebGL = IsWebGLBasedSpec(mShaderSpec);
    if ((!mFragmentOutputsWithLocation.empty() && !mFragmentOutputsWithoutLocation.empty()) ||
        mFragmentOutputsWithoutLocation.size() > 1)
    {
        const char *unspecifiedLocationErrorMessage = nullptr;
        if (!isExtensionEnabled(TExtension::EXT_blend_func_extended))
        {
            unspecifiedLocationErrorMessage =
                "when EXT_blend_func_extended extension is not enabled, must explicitly specify "
                "all locations when using multiple fragment outputs";
        }
        else if (!mPLSLayouts.empty())
        {
            unspecifiedLocationErrorMessage =
                "must explicitly specify all locations when using multiple fragment outputs and "
                "pixel local storage, even if EXT_blend_func_extended is enabled";
        }
        else if (isWebGL)
        {
            unspecifiedLocationErrorMessage =
                "must explicitly specify all locations when using multiple fragment outputs "
                "in WebGL contexts, even if EXT_blend_func_extended is enabled";
        }
        if (unspecifiedLocationErrorMessage != nullptr)
        {
            for (const VariableAndLocation &variable : mFragmentOutputsWithoutLocation)
            {
                error(variable.line, unspecifiedLocationErrorMessage, variable.variable->name());
            }
        }
    }

    if (!mFragmentOutputsYuv.empty() &&
        (mFragmentOutputsYuv.size() > 1 || mFragmentOutputFragDepthUsed ||
         !mFragmentOutputsWithLocation.empty() || !mFragmentOutputsWithoutLocation.empty()))
    {
        for (const VariableAndLocation &variable : mFragmentOutputsYuv)
        {
            error(variable.line,
                  "not allowed to specify yuv qualifier when using depth or multiple color "
                  "fragment outputs",
                  variable.variable->name());
        }
    }

    // If gl_SecondaryFragDataEXT is used, then indices to gl_FragData must be smaller than
    // gl_MaxDualSourceDrawBuffersEXT.  This cannot be validated until the end of the shader because
    // it would be unknown if gl_SecondaryFragDataEXT is ever used.
    //
    // Note that gl_SecondaryFragColorEXT is not checked, because simultaneous use of gl_FragData
    // and gl_SecondaryFragColorEXT is already forbidden.  Additionally, mFragmentOutputIndex1Used
    // is not checked as it pertains to ESSL 300+.
    const bool secondaryFragDataUsed =
        symbolTable.gl_SecondaryFragDataEXT() != nullptr &&
        symbolTable.isStaticallyUsed(*symbolTable.gl_SecondaryFragDataEXT());
    if (secondaryFragDataUsed && mMaxFragDataArrayIndexUsed >= mResources.MaxDualSourceDrawBuffers)
    {
        mDiagnostics->globalError(
            "array index for gl_FragData must be less than "
            "GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT when "
            "gl_SecondaryFragDataEXT is used");
    }
}

bool TParseContext::postParseChecks()
{
#ifndef ANGLE_IR
    // If parse failed, we shouldn't reach here.
    ASSERT(!mCompileOptions.useIR || mTreeRoot != nullptr);
#endif

    // Struct declarations are delayed to the end of parse, add them to the AST now
    if (mTreeRoot != nullptr)
    {
        prependPendingStructDeclarations();
    }

    // If gl_Position is expected to be zero-initialized, make sure it's declared to the IR; it
    // should still be done if gl_Position is statically not used by the shader.
    if (mCompileOptions.initGLPosition)
    {
        const TSymbol *glPosition =
            symbolTable.find(ImmutableString("gl_Position"), getShaderVersion());
        ASSERT(glPosition != nullptr && glPosition->isVariable());
        declareBuiltInOnFirstUse(static_cast<const TVariable *>(glPosition));
    }

    if (mMainFunction == nullptr)
    {
        error(kNoSourceLoc, "Missing main()", "");
        return false;
    }

    for (TType *type : mDeferredArrayTypesToSize)
    {
        error(kNoSourceLoc, "Unsized global array type: ", type->getBasicString());
    }

    // Clip/cull distance validation now that the size can be determined.
    if (mClipDistanceInfo.size == 0 && mClipDistanceInfo.hasNonConstIndex)
    {
        error(mClipDistanceInfo.firstEncounter,
              "The gl_ClipDistance array must be sized by the shader either redeclaring it with a "
              "size or indexing it only with constant integral expressions",
              "gl_ClipDistance");
    }

    if (mCullDistanceInfo.size == 0 && mCullDistanceInfo.hasNonConstIndex)
    {
        error(mCullDistanceInfo.firstEncounter,
              "The gl_CullDistance array must be sized by the shader either redeclaring it with a "
              "size or indexing it only with constant integral expressions",
              "gl_CullDistance");
    }

    const unsigned int usedClipDistances = getClipDistanceArraySize();
    const unsigned int usedCullDistances = getCullDistanceArraySize();
    const unsigned int combinedClipAndCullDistances =
        usedClipDistances > 0 && usedCullDistances > 0 ? usedClipDistances + usedCullDistances : 0;

    // When cull distances are not supported, i.e., when GL_ANGLE_clip_cull_distance is
    // exposed but GL_EXT_clip_cull_distance is not exposed, the combined limit is 0.
    if (usedCullDistances > 0 && mResources.MaxCombinedClipAndCullDistances == 0)
    {
        error(mCullDistanceInfo.firstEncounter, "Cull distance functionality is not available",
              "gl_CullDistance");
    }

    if (static_cast<int>(combinedClipAndCullDistances) > mResources.MaxCombinedClipAndCullDistances)
    {
        std::stringstream strstr = sh::InitializeStream<std::stringstream>();
        strstr << "The sum of 'gl_ClipDistance' and 'gl_CullDistance' size is greater than "
                  "gl_MaxCombinedClipAndCullDistances ("
               << combinedClipAndCullDistances << " > "
               << mResources.MaxCombinedClipAndCullDistances << ")";
        error(mClipDistanceInfo.firstEncounter, strstr.str().c_str(), "gl_ClipDistance");
    }

    if (mClipDistanceInfo.hasArrayLengthMethodCall && usedClipDistances == 0)
    {
        error(mClipDistanceInfo.firstEncounter,
              "The length() method cannot be called on gl_ClipDistance that is not "
              "runtime sized and also has not yet been explicitly sized",
              "gl_ClipDistance");
    }
    if (mCullDistanceInfo.hasArrayLengthMethodCall && usedCullDistances == 0)
    {
        error(mCullDistanceInfo.firstEncounter,
              "The length() method cannot be called on gl_CullDistance that is not "
              "runtime sized and also has not yet been explicitly sized",
              "gl_CullDistance");
    }

    if (ir::IsVariableIdValid(mClipDistanceInfo.id) && usedClipDistances > 0 &&
        !isClipDistanceRedeclared())
    {
        mIRBuilder.onGlClipDistanceSized(mClipDistanceInfo.id, usedClipDistances);
    }
    if (ir::IsVariableIdValid(mCullDistanceInfo.id) && usedCullDistances > 0 &&
        !isCullDistanceRedeclared())
    {
        mIRBuilder.onGlCullDistanceSized(mCullDistanceInfo.id, usedCullDistances);
    }

    ValidateFragColorAndFragData(mShaderType, mShaderVersion, symbolTable, mDiagnostics);
    postParseValidateFragmentOutputLocations();

    if (mCompileOptions.rejectWebglShadersWithLargeVariables)
    {
        if (mTotalPrivateVariablesSize.ValueOrDefault(std::numeric_limits<size_t>::max()) >
            kWebGLMaxTotalPrivateVariableSizeInBytes)
        {
            error(TSourceLoc{},
                  "Total size of declared private variables exceeds implementation-defined limit",
                  "");
        }
    }

    if (mCompileOptions.rejectWebglShadersWithUndefinedBehavior)
    {
        // For any possibly infinite loops, check if the loop variable remained unchanged and so the
        // loop is in fact definitely an infinite loop.
        for (VariableAndLocation loopVariable : mPossiblyInfiniteLoops)
        {
            if (mConstantTrueVariables.find(loopVariable.variable->uniqueId()) !=
                mConstantTrueVariables.end())
            {
                error(loopVariable.line, "Infinite loop detected in the shader",
                      loopVariable.variable->name());
            }
        }
    }

    // When PLS planes are emulated with storage images, early_fragment_tests has to be specified.
    // Until codegen is done from the IR itself, set this flag here in anticipation, avoiding a need
    // for the PLS transformation in IR to make an FFI call to set it in TCompiler.  This can be
    // removed after codegen is no longer done from AST.
    if (mCompileOptions.useIR && !mPLSLayouts.empty() &&
        mCompileOptions.pls.type == ShPixelLocalStorageType::ImageLoadStore)
    {
        mEarlyFragmentTestsSpecified = true;
        // No need to set it for the IR, the PLS rewrite transformation will do that.
    }

    if (!checkCanUseShaderType(kNoSourceLoc))
    {
        return false;
    }

    checkCallGraph();

    return numErrors() == 0;
}

//
// Parse an array of strings using yyparse.
//
// Returns 0 for success.
//
int PaParseStrings(angle::Span<const char *const> string,
                   const int length[],
                   TParseContext *context)
{
    if (string.empty())
    {
        return 1;
    }

    if (glslang_initialize(context))
    {
        return 1;
    }

    int error = glslang_scan(string.size(), string.data(), length, context);
    if (!error)
    {
        error = glslang_parse(context);
    }

    glslang_finalize(context);

    return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
}

}  // namespace sh
