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

#include "compiler/translator/ValidateAST.h"

#include "common/utilities.h"
#include "compiler/translator/Diagnostics.h"
#include "compiler/translator/ImmutableStringBuilder.h"
#include "compiler/translator/Name.h"
#include "compiler/translator/Symbol.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
#include "compiler/translator/tree_util/SpecializationConstant.h"
#include "compiler/translator/util.h"

namespace sh
{

namespace
{

class ValidateAST : public TIntermTraverser
{
  public:
    static bool validate(TIntermNode *root,
                         TDiagnostics *diagnostics,
                         const ValidateASTOptions &options);

    void visitSymbol(TIntermSymbol *node) override;
    void visitConstantUnion(TIntermConstantUnion *node) override;
    bool visitSwizzle(Visit visit, TIntermSwizzle *node) override;
    bool visitBinary(Visit visit, TIntermBinary *node) override;
    bool visitUnary(Visit visit, TIntermUnary *node) override;
    bool visitTernary(Visit visit, TIntermTernary *node) override;
    bool visitIfElse(Visit visit, TIntermIfElse *node) override;
    bool visitSwitch(Visit visit, TIntermSwitch *node) override;
    bool visitCase(Visit visit, TIntermCase *node) override;
    void visitFunctionPrototype(TIntermFunctionPrototype *node) override;
    bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
    bool visitAggregate(Visit visit, TIntermAggregate *node) override;
    bool visitBlock(Visit visit, TIntermBlock *node) override;
    bool visitGlobalQualifierDeclaration(Visit visit,
                                         TIntermGlobalQualifierDeclaration *node) override;
    bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
    bool visitLoop(Visit visit, TIntermLoop *node) override;
    bool visitBranch(Visit visit, TIntermBranch *node) override;
    void visitPreprocessorDirective(TIntermPreprocessorDirective *node) override;

  private:
    ValidateAST(TIntermNode *root, TDiagnostics *diagnostics, const ValidateASTOptions &options);

    // Visit as a generic node
    void visitNode(Visit visit, TIntermNode *node);
    // Visit a structure or interface block, and recursively visit its fields of structure type.
    void visitStructOrInterfaceBlockDeclaration(const TType &type, const TSourceLoc &location);
    void visitStructUsage(const TType &type, const TSourceLoc &location);
    // Visit a unary or aggregate node and validate its built-in op against its built-in function.
    void visitBuiltInFunction(TIntermOperator *op, const TFunction *function);
    // Visit an aggregate node and validate its function call is to one that's already defined.
    void visitFunctionCall(TIntermAggregate *node);
    // Visit a binary node and validate its type against its operands.
    void validateExpressionTypeBinary(TIntermBinary *node);
    // Visit a switch node and validate its selector type is integer.
    void validateExpressionTypeSwitch(TIntermSwitch *node);
    // Visit a symbol node and validate it's declared previously.
    void visitVariableNeedingDeclaration(TIntermSymbol *node);
    // Visit a built-in symbol node and validate it's consistently used across the tree.
    void visitBuiltInVariable(TIntermSymbol *node);

    void scope(Visit visit);
    bool isVariableDeclared(const TVariable *variable);
    bool variableNeedsDeclaration(const TVariable *variable);
    const TFieldListCollection *getStructOrInterfaceBlock(const TType &type, Name *typeNameOut);

    void expectNonNullChildren(Visit visit, TIntermNode *node, size_t least_count);

    bool validateInternal();
    bool isInDeclaration() const;

    ValidateASTOptions mOptions;
    TDiagnostics *mDiagnostics;

    // For validateSingleParent:
    std::map<TIntermNode *, TIntermNode *> mParent;
    bool mSingleParentFailed = false;

    // For validateVariableReferences:
    std::vector<std::set<const TVariable *>> mDeclaredVariables;
    std::set<const TInterfaceBlock *> mNamelessInterfaceBlocks;
    std::map<ImmutableString, TSymbolUniqueId> mReferencedBuiltIns;
    bool mVariableReferencesFailed = false;

    // For validateOps:
    bool mOpsFailed = false;

    // For validateBuiltInOps:
    bool mBuiltInOpsFailed = false;

    // For validateFunctionCall:
    std::set<const TFunction *> mDeclaredFunctions;
    bool mFunctionCallFailed = false;

    // For validateNoRawFunctionCalls:
    bool mNoRawFunctionCallsFailed = false;

    // For validateNullNodes:
    bool mNullNodesFailed = false;

    // For validateQualifiers:
    bool mQualifiersFailed = false;

    // For validatePrecision:
    bool mPrecisionFailed = false;

    // For validateStructUsage:
    std::vector<std::map<Name, const TFieldListCollection *>> mStructsAndBlocksByName;
    std::set<const TFunction *> mStructUsageProcessedFunctions;
    bool mStructUsageFailed = false;

    // For validateExpressionTypes:
    bool mExpressionTypesFailed = false;

    // For validateMultiDeclarations:
    bool mMultiDeclarationsFailed = false;

    // For validateNoSwizzleOfSwizzle:
    bool mNoSwizzleOfSwizzleFailed = false;

    // For validateNoQualifiersOnConstructors:
    bool mNoQualifiersOnConstructorsFailed = false;

    // For validateNoStatementsAfterBranch:
    bool mIsBranchVisitedInBlock        = false;
    bool mNoStatementsAfterBranchFailed = false;

    bool mVariableNamingFailed = false;
};

bool IsSameType(const TType &a, const TType &b)
{
    return a.getBasicType() == b.getBasicType() && a.getNominalSize() == b.getNominalSize() &&
           a.getSecondarySize() == b.getSecondarySize() && a.getArraySizes() == b.getArraySizes() &&
           a.getStruct() == b.getStruct() &&
           (!a.isInterfaceBlock() || a.getInterfaceBlock() == b.getInterfaceBlock());
}

bool IsUnaryOp(TOperator op)
{
    switch (op)
    {
        case EOpNegative:
        case EOpPositive:
        case EOpLogicalNot:
        case EOpBitwiseNot:
        case EOpPostIncrement:
        case EOpPostDecrement:
        case EOpPreIncrement:
        case EOpPreDecrement:
        case EOpArrayLength:
            return true;
        default:
            return false;
    }
}

bool IsBinaryOp(TOperator op)
{
    switch (op)
    {
        case EOpAdd:
        case EOpSub:
        case EOpMul:
        case EOpDiv:
        case EOpIMod:
        case EOpEqual:
        case EOpNotEqual:
        case EOpLessThan:
        case EOpGreaterThan:
        case EOpLessThanEqual:
        case EOpGreaterThanEqual:
        case EOpComma:
        case EOpVectorTimesScalar:
        case EOpVectorTimesMatrix:
        case EOpMatrixTimesVector:
        case EOpMatrixTimesScalar:
        case EOpMatrixTimesMatrix:
        case EOpLogicalOr:
        case EOpLogicalXor:
        case EOpLogicalAnd:
        case EOpBitShiftLeft:
        case EOpBitShiftRight:
        case EOpBitwiseAnd:
        case EOpBitwiseXor:
        case EOpBitwiseOr:
        case EOpIndexDirect:
        case EOpIndexIndirect:
        case EOpIndexDirectStruct:
        case EOpIndexDirectInterfaceBlock:
        case EOpAssign:
        case EOpInitialize:
        case EOpAddAssign:
        case EOpSubAssign:
        case EOpMulAssign:
        case EOpVectorTimesMatrixAssign:
        case EOpVectorTimesScalarAssign:
        case EOpMatrixTimesScalarAssign:
        case EOpMatrixTimesMatrixAssign:
        case EOpDivAssign:
        case EOpIModAssign:
        case EOpBitShiftLeftAssign:
        case EOpBitShiftRightAssign:
        case EOpBitwiseAndAssign:
        case EOpBitwiseXorAssign:
        case EOpBitwiseOrAssign:
            return true;
        default:
            return false;
    }
}

bool IsBranchOp(TOperator op)
{
    switch (op)
    {
        case EOpKill:
        case EOpReturn:
        case EOpBreak:
        case EOpContinue:
            return true;
        default:
            return false;
    }
}

bool ValidateAST::validate(TIntermNode *root,
                           TDiagnostics *diagnostics,
                           const ValidateASTOptions &options)
{
    ValidateAST validate(root, diagnostics, options);
    root->traverse(&validate);
    return validate.validateInternal();
}

ValidateAST::ValidateAST(TIntermNode *root,
                         TDiagnostics *diagnostics,
                         const ValidateASTOptions &options)
    : TIntermTraverser(true, false, true, nullptr), mOptions(options), mDiagnostics(diagnostics)
{
    bool isTreeRoot = root->getAsBlock() && root->getAsBlock()->isTreeRoot();

    // Some validations are not applicable unless run on the entire tree.
    if (!isTreeRoot)
    {
        mOptions.validateVariableReferences = false;
        mOptions.validateFunctionCall       = false;
        mOptions.validateStructUsage        = false;
    }

    if (mOptions.validateSingleParent)
    {
        mParent[root] = nullptr;
    }
}

void ValidateAST::visitNode(Visit visit, TIntermNode *node)
{
    if (visit == PreVisit && mOptions.validateSingleParent)
    {
        size_t childCount = node->getChildCount();
        for (size_t i = 0; i < childCount; ++i)
        {
            TIntermNode *child = node->getChildNode(i);
            if (mParent.find(child) != mParent.end())
            {
                // If child is visited twice but through the same parent, the problem is in one of
                // the ancestors.
                if (mParent[child] != node)
                {
                    mDiagnostics->error(node->getLine(), "Found child with two parents",
                                        "<validateSingleParent>");
                    mSingleParentFailed = true;
                }
            }

            mParent[child] = node;
        }
    }

    if (visit == PreVisit && mOptions.validateNoStatementsAfterBranch)
    {
        // If a branch has already been visited in this block, there should be no statements that
        // follow.  Only expected node visit should be PostVisit of the block.
        if (mIsBranchVisitedInBlock)
        {
            mDiagnostics->error(node->getLine(), "Found dead code after branch",
                                "<validateNoStatementsAfterBranch>");
            mNoStatementsAfterBranchFailed = true;
        }
    }
}

void ValidateAST::visitStructOrInterfaceBlockDeclaration(const TType &type,
                                                         const TSourceLoc &location)
{
    if (type.getStruct() == nullptr && type.getInterfaceBlock() == nullptr)
    {
        return;
    }

    // Make sure the structure or interface block is not doubly defined.
    Name typeName;
    const TFieldListCollection *namedStructOrBlock = getStructOrInterfaceBlock(type, &typeName);

    // Recurse the fields of the structure or interface block and check members of structure type.
    // This is done before visiting the struct itself, because if the fields refer to a struct with
    // the same name, they would be referencing the struct declared in an outer scope.
    {
        // Note that structOrBlock was previously only set for named structures, so make sure
        // nameless structs are also recursed.
        const TFieldListCollection *structOrBlock = namedStructOrBlock;
        if (structOrBlock == nullptr)
        {
            structOrBlock = type.getStruct();
        }
        ASSERT(structOrBlock != nullptr);

        for (const TField *field : structOrBlock->fields())
        {
            visitStructUsage(*field->type(), field->line());
        }
    }

    if (namedStructOrBlock)
    {
        ASSERT(!typeName.empty());
        // Structures are not allowed to be doubly defined
        if (type.getStruct() == nullptr)
        {
            // Allow interfaces to be doubly-defined.
            ImmutableString rawName = typeName.rawName();

            if (IsShaderIn(type.getQualifier()))
            {
                rawName = BuildConcatenatedImmutableString(rawName, "<input>");
            }
            else if (IsShaderOut(type.getQualifier()))
            {
                rawName = BuildConcatenatedImmutableString(rawName, "<output>");
            }
            else if (IsStorageBuffer(type.getQualifier()))
            {
                rawName = BuildConcatenatedImmutableString(rawName, "<buffer>");
            }
            else if (type.getQualifier() == EvqUniform)
            {
                rawName = BuildConcatenatedImmutableString(rawName, "<uniform>");
            }
            typeName = Name(rawName, typeName.symbolType());
        }

        if (mStructsAndBlocksByName.back().find(typeName) != mStructsAndBlocksByName.back().end())
        {
            mDiagnostics->error(location,
                                "Found redeclaration of struct or interface block with the same "
                                "name in the same scope <validateStructUsage>",
                                typeName.rawName().data());
            mStructUsageFailed = true;
        }
        else
        {
            // First encounter.
            mStructsAndBlocksByName.back()[typeName] = namedStructOrBlock;
        }
    }
}

void ValidateAST::visitStructUsage(const TType &type, const TSourceLoc &location)
{
    if (type.getStruct() == nullptr)
    {
        return;
    }

    // Make sure the structure being referenced has the same pointer as the closest (in scope)
    // definition.
    const TStructure *structure     = type.getStruct();
    const Name typeName(*structure);

    bool foundDeclaration = false;
    for (size_t scopeIndex = mStructsAndBlocksByName.size(); scopeIndex > 0; --scopeIndex)
    {
        const std::map<Name, const TFieldListCollection *> &scopeDecls =
            mStructsAndBlocksByName[scopeIndex - 1];

        auto iter = scopeDecls.find(typeName);
        if (iter != scopeDecls.end())
        {
            foundDeclaration = true;

            if (iter->second != structure)
            {
                mDiagnostics->error(location,
                                    "Found reference to struct or interface block with doubly "
                                    "created type <validateStructUsage>",
                                    typeName.rawName().data());
                mStructUsageFailed = true;
            }

            break;
        }
    }

    if (!foundDeclaration)
    {
        mDiagnostics->error(location,
                            "Found reference to struct or interface block with no declaration "
                            "<validateStructUsage>",
                            typeName.rawName().data());
        mStructUsageFailed = true;
    }
}

void ValidateAST::visitBuiltInFunction(TIntermOperator *node, const TFunction *function)
{
    const TOperator op = node->getOp();
    if (!BuiltInGroup::IsBuiltIn(op))
    {
        return;
    }

    ImmutableString opValue = BuildConcatenatedImmutableString("op: ", op);
    if (function == nullptr)
    {
        mDiagnostics->error(node->getLine(),
                            "Found node calling built-in without a reference to the built-in "
                            "function <validateBuiltInOps>",
                            opValue.data());
        mVariableReferencesFailed = true;
    }
    else if (function->getBuiltInOp() != op)
    {
        mDiagnostics->error(node->getLine(),
                            "Found node calling built-in with a reference to a different function "
                            "<validateBuiltInOps>",
                            opValue.data());
        mVariableReferencesFailed = true;
    }
}

void ValidateAST::visitFunctionCall(TIntermAggregate *node)
{
    if (node->getOp() != EOpCallFunctionInAST)
    {
        return;
    }

    const TFunction *function = node->getFunction();

    if (function == nullptr)
    {
        mDiagnostics->error(node->getLine(),
                            "Found node calling function without a reference to it",
                            "<validateFunctionCall>");
        mFunctionCallFailed = true;
    }
    else if (mDeclaredFunctions.find(function) == mDeclaredFunctions.end())
    {
        mDiagnostics->error(node->getLine(),
                            "Found node calling previously undeclared function "
                            "<validateFunctionCall>",
                            function->name().data());
        mFunctionCallFailed = true;
    }
}

void ValidateAST::validateExpressionTypeBinary(TIntermBinary *node)
{
    switch (node->getOp())
    {
        case EOpIndexDirect:
        case EOpIndexIndirect:
        {
            TType expectedType(node->getLeft()->getType());
            if (!expectedType.isArray())
            {
                // TODO: Validate matrix column selection and vector component selection.
                // http://anglebug.com/42261441
                break;
            }

            expectedType.toArrayElementType();

            if (!IsSameType(node->getType(), expectedType))
            {
                const TSymbol *symbol = expectedType.getStruct();
                if (symbol == nullptr)
                {
                    symbol = expectedType.getInterfaceBlock();
                }
                const char *name = nullptr;
                if (symbol)
                {
                    name = symbol->name().data();
                }
                else if (expectedType.isScalar())
                {
                    name = "<scalar array>";
                }
                else if (expectedType.isVector())
                {
                    name = "<vector array>";
                }
                else
                {
                    ASSERT(expectedType.isMatrix());
                    name = "<matrix array>";
                }

                mDiagnostics->error(
                    node->getLine(),
                    "Found index node with type that is inconsistent with the array being indexed "
                    "<validateExpressionTypes>",
                    name);
                mExpressionTypesFailed = true;
            }
        }
        break;
        default:
            // TODO: Validate other expressions. http://anglebug.com/42261441
            break;
    }

    switch (node->getOp())
    {
        case EOpIndexDirect:
        case EOpIndexDirectStruct:
        case EOpIndexDirectInterfaceBlock:
            if (node->getRight()->getAsConstantUnion() == nullptr)
            {
                mDiagnostics->error(node->getLine(),
                                    "Found direct index node with a non-constant index",
                                    "<validateExpressionTypes>");
                mExpressionTypesFailed = true;
            }
            break;
        default:
            break;
    }
}

void ValidateAST::validateExpressionTypeSwitch(TIntermSwitch *node)
{
    const TType &selectorType = node->getInit()->getType();

    if (selectorType.getBasicType() != EbtYuvCscStandardEXT &&
        selectorType.getBasicType() != EbtInt && selectorType.getBasicType() != EbtUInt)
    {
        mDiagnostics->error(node->getLine(), "Found switch selector expression that is not integer",
                            "<validateExpressionTypes>");
        mExpressionTypesFailed = true;
    }
    else if (!selectorType.isScalar())
    {
        mDiagnostics->error(node->getLine(), "Found switch selector expression that is not scalar",
                            "<validateExpressionTypes>");
        mExpressionTypesFailed = true;
    }
}

void ValidateAST::visitVariableNeedingDeclaration(TIntermSymbol *node)
{
    const TVariable *variable = &node->variable();
    const TType &type         = node->getType();

    // If it's a reference to a field of a nameless interface block, match it by index and name.
    if (type.getInterfaceBlock() && !type.isInterfaceBlock())
    {
        const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
        const TFieldList &fieldList           = interfaceBlock->fields();
        const size_t fieldIndex               = type.getInterfaceBlockFieldIndex();

        if (mNamelessInterfaceBlocks.count(interfaceBlock) == 0)
        {
            mDiagnostics->error(node->getLine(),
                                "Found reference to undeclared or inconsistenly transformed "
                                "nameless interface block <validateVariableReferences>",
                                node->getName().data());
            mVariableReferencesFailed = true;
        }
        else if (fieldIndex >= fieldList.size() || node->getName() != fieldList[fieldIndex]->name())
        {
            mDiagnostics->error(node->getLine(),
                                "Found reference to inconsistenly transformed nameless "
                                "interface block field <validateVariableReferences>",
                                node->getName().data());
            mVariableReferencesFailed = true;
        }
        return;
    }

    const bool isStructDeclaration =
        type.isStructSpecifier() && variable->symbolType() == SymbolType::Empty;

    if (!isStructDeclaration && !isVariableDeclared(variable))
    {
        mDiagnostics->error(node->getLine(),
                            "Found reference to undeclared or inconsistently transformed "
                            "variable <validateVariableReferences>",
                            node->getName().data());
        mVariableReferencesFailed = true;
    }
}

void ValidateAST::visitBuiltInVariable(TIntermSymbol *node)
{
    const TVariable *variable = &node->variable();
    ImmutableString name      = variable->name();

    if (mOptions.validateVariableReferences)
    {
        auto iter = mReferencedBuiltIns.find(name);
        if (iter == mReferencedBuiltIns.end())
        {
            mReferencedBuiltIns.emplace(name, variable->uniqueId());
            return;
        }

        if (variable->uniqueId() != iter->second)
        {
            mDiagnostics->error(
                node->getLine(),
                "Found inconsistent references to built-in variable <validateVariableReferences>",
                name.data());
            mVariableReferencesFailed = true;
        }
    }

    if (mOptions.validateQualifiers)
    {
        TQualifier qualifier = variable->getType().getQualifier();

        if ((name == "gl_ClipDistance" && qualifier != EvqClipDistance) ||
            (name == "gl_CullDistance" && qualifier != EvqCullDistance) ||
            (name == "gl_FragDepth" && qualifier != EvqFragDepth) ||
            (name == "gl_FragDepthEXT" && qualifier != EvqFragDepth) ||
            (name == "gl_LastFragData" && qualifier != EvqLastFragData) ||
            (name == "gl_LastFragColorARM" && qualifier != EvqLastFragColor) ||
            (name == "gl_LastFragDepthARM" && qualifier != EvqLastFragDepth) ||
            (name == "gl_LastFragStencilARM" && qualifier != EvqLastFragStencil) ||
            (name == "gl_DepthRange" && qualifier != EvqDepthRange) ||
            (name == "gl_NumSamples" && qualifier != EvqNumSamples))
        {
            mDiagnostics->error(
                node->getLine(),
                "Incorrect qualifier applied to redeclared built-in <validateQualifiers>",
                name.data());
            mQualifiersFailed = true;
        }
    }
}

void ValidateAST::scope(Visit visit)
{
    if (mOptions.validateVariableReferences)
    {
        if (visit == PreVisit)
        {
            mDeclaredVariables.push_back({});
        }
        else if (visit == PostVisit)
        {
            mDeclaredVariables.pop_back();
        }
    }

    if (mOptions.validateStructUsage)
    {
        if (visit == PreVisit)
        {
            mStructsAndBlocksByName.push_back({});
        }
        else if (visit == PostVisit)
        {
            mStructsAndBlocksByName.pop_back();
        }
    }
}

bool ValidateAST::isVariableDeclared(const TVariable *variable)
{
    ASSERT(mOptions.validateVariableReferences);

    for (const std::set<const TVariable *> &scopeVariables : mDeclaredVariables)
    {
        if (scopeVariables.count(variable) > 0)
        {
            return true;
        }
    }

    return false;
}

bool ValidateAST::variableNeedsDeclaration(const TVariable *variable)
{
    // Don't expect declaration for built-in variables.
    if (gl::IsBuiltInName(variable->name().data()))
    {
        return false;
    }

    // Additionally, don't expect declaration for Vulkan specialization constants if not enabled.
    // The declaration of these variables is deferred.
    if (variable->getType().getQualifier() == EvqSpecConst)
    {
        return mOptions.validateSpecConstReferences;
    }

    return true;
}

const TFieldListCollection *ValidateAST::getStructOrInterfaceBlock(const TType &type,
                                                                   Name *typeNameOut)
{
    const TStructure *structure           = type.getStruct();
    const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();

    ASSERT(structure != nullptr || interfaceBlock != nullptr);

    // Make sure the structure or interface block is not doubly defined.
    const TFieldListCollection *structOrBlock = nullptr;
    if (structure != nullptr && structure->symbolType() != SymbolType::Empty)
    {
        structOrBlock = structure;
        *typeNameOut  = Name(*structure);
    }
    else if (interfaceBlock != nullptr)
    {
        structOrBlock = interfaceBlock;
        *typeNameOut  = Name(*interfaceBlock);
    }

    return structOrBlock;
}

void ValidateAST::expectNonNullChildren(Visit visit, TIntermNode *node, size_t least_count)
{
    if (visit == PreVisit && mOptions.validateNullNodes)
    {
        size_t childCount = node->getChildCount();
        if (childCount < least_count)
        {
            mDiagnostics->error(node->getLine(), "Too few children", "<validateNullNodes>");
            mNullNodesFailed = true;
        }

        for (size_t i = 0; i < childCount; ++i)
        {
            if (node->getChildNode(i) == nullptr)
            {
                mDiagnostics->error(node->getLine(), "Found nullptr child", "<validateNullNodes>");
                mNullNodesFailed = true;
            }
        }
    }
}

void ValidateAST::visitSymbol(TIntermSymbol *node)
{
    visitNode(PreVisit, node);

    const TVariable *variable = &node->variable();

    if (mOptions.validateVariableReferences)
    {
        if (variableNeedsDeclaration(variable))
        {
            visitVariableNeedingDeclaration(node);
        }
    }
    if (variable->symbolType() == SymbolType::Empty &&
        variable->getType().getInterfaceBlock() == nullptr)
    {
        if (!isInDeclaration())
        {
            mDiagnostics->error(node->getLine(), "Found symbol with empty name", "");
            mVariableNamingFailed = true;
        }
    }
    const bool isBuiltIn = gl::IsBuiltInName(variable->name().data());
    if (isBuiltIn)
    {
        visitBuiltInVariable(node);
    }

    if (mOptions.validatePrecision)
    {
        if (!isBuiltIn && IsPrecisionApplicableToType(node->getBasicType()) &&
            node->getType().getPrecision() == EbpUndefined)
        {
            // Note that some built-ins don't have a precision.
            mDiagnostics->error(node->getLine(),
                                "Found symbol with undefined precision <validatePrecision>",
                                variable->name().data());
            mPrecisionFailed = true;
        }
    }
}

void ValidateAST::visitConstantUnion(TIntermConstantUnion *node)
{
    visitNode(PreVisit, node);
}

bool ValidateAST::visitSwizzle(Visit visit, TIntermSwizzle *node)
{
    visitNode(visit, node);

    if (mOptions.validateNoSwizzleOfSwizzle)
    {
        if (node->getOperand()->getAsSwizzleNode() != nullptr)
        {
            mDiagnostics->error(node->getLine(), "Found swizzle applied to swizzle",
                                "<validateNoSwizzleOfSwizzle>");
            mNoSwizzleOfSwizzleFailed = true;
        }
    }

    return true;
}

bool ValidateAST::visitBinary(Visit visit, TIntermBinary *node)
{
    visitNode(visit, node);

    if (visit == PreVisit && mOptions.validateOps)
    {
        const bool hasParent = getParentNode() != nullptr;
        const bool isInDeclaration =
            hasParent && getParentNode()->getAsDeclarationNode() != nullptr;
        const TOperator op = node->getOp();
        if (!BuiltInGroup::IsBuiltIn(op) && !IsBinaryOp(op))
        {
            mDiagnostics->error(node->getLine(),
                                "Found binary node with non-binary op <validateOps>",
                                GetOperatorString(op));
            mOpsFailed = true;
        }
        else if (op == EOpInitialize && hasParent && !isInDeclaration)
        {
            mDiagnostics->error(node->getLine(),
                                "Found EOpInitialize node outside declaration <validateOps>",
                                GetOperatorString(op));
            mOpsFailed = true;
        }
        else if (op == EOpAssign && hasParent && isInDeclaration)
        {
            mDiagnostics->error(node->getLine(),
                                "Found EOpAssign node inside declaration <validateOps>",
                                GetOperatorString(op));
            mOpsFailed = true;
        }
    }
    if (mOptions.validateExpressionTypes && visit == PreVisit)
    {
        validateExpressionTypeBinary(node);
    }

    return true;
}

bool ValidateAST::visitUnary(Visit visit, TIntermUnary *node)
{
    visitNode(visit, node);

    if (visit == PreVisit && mOptions.validateOps)
    {
        const TOperator op = node->getOp();
        if (!BuiltInGroup::IsBuiltIn(op) && !IsUnaryOp(op))
        {
            mDiagnostics->error(node->getLine(), "Found unary node with non-unary op <validateOps>",
                                GetOperatorString(op));
            mOpsFailed = true;
        }
    }
    if (visit == PreVisit && mOptions.validateBuiltInOps)
    {
        visitBuiltInFunction(node, node->getFunction());
    }

    return true;
}

bool ValidateAST::visitTernary(Visit visit, TIntermTernary *node)
{
    visitNode(visit, node);
    return true;
}

bool ValidateAST::visitIfElse(Visit visit, TIntermIfElse *node)
{
    visitNode(visit, node);
    return true;
}

bool ValidateAST::visitSwitch(Visit visit, TIntermSwitch *node)
{
    visitNode(visit, node);

    if (mOptions.validateExpressionTypes && visit == PreVisit)
    {
        validateExpressionTypeSwitch(node);
    }

    return true;
}

bool ValidateAST::visitCase(Visit visit, TIntermCase *node)
{
    // Case is allowed to come after a branch, and for dead-code-elimination purposes acts as if a
    // new block is started.
    mIsBranchVisitedInBlock = false;

    visitNode(visit, node);

    return true;
}

void ValidateAST::visitFunctionPrototype(TIntermFunctionPrototype *node)
{
    visitNode(PreVisit, node);

    if (mOptions.validateFunctionCall)
    {
        const TFunction *function = node->getFunction();
        mDeclaredFunctions.insert(function);
    }

    const TFunction *function = node->getFunction();
    const TType &returnType   = function->getReturnType();
    if (mOptions.validatePrecision && IsPrecisionApplicableToType(returnType.getBasicType()) &&
        returnType.getPrecision() == EbpUndefined)
    {
        mDiagnostics->error(
            node->getLine(),
            "Found function with undefined precision on return value <validatePrecision>",
            function->name().data());
        mPrecisionFailed = true;
    }

    if (mOptions.validateStructUsage)
    {
        bool needsProcessing =
            mStructUsageProcessedFunctions.find(function) == mStructUsageProcessedFunctions.end();
        if (needsProcessing && returnType.isStructSpecifier())
        {
            visitStructOrInterfaceBlockDeclaration(returnType, node->getLine());
            mStructUsageProcessedFunctions.insert(function);
        }
        else
        {
            visitStructUsage(returnType, node->getLine());
        }
    }

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

        if (mOptions.validateStructUsage)
        {
            visitStructUsage(paramType, node->getLine());
        }

        if (mOptions.validateQualifiers)
        {
            TQualifier qualifier = paramType.getQualifier();
            if (qualifier != EvqParamIn && qualifier != EvqParamOut && qualifier != EvqParamInOut &&
                qualifier != EvqParamConst)
            {
                mDiagnostics->error(node->getLine(),
                                    "Found function prototype with an invalid qualifier "
                                    "<validateQualifiers>",
                                    param->name().data());
                mQualifiersFailed = true;
            }

            if (IsOpaqueType(paramType.getBasicType()) && qualifier != EvqParamIn)
            {
                mDiagnostics->error(
                    node->getLine(),
                    "Found function prototype with an invalid qualifier on opaque parameter "
                    "<validateQualifiers>",
                    param->name().data());
                mQualifiersFailed = true;
            }
        }

        if (mOptions.validatePrecision && IsPrecisionApplicableToType(paramType.getBasicType()) &&
            paramType.getPrecision() == EbpUndefined)
        {
            mDiagnostics->error(
                node->getLine(),
                "Found function parameter with undefined precision <validatePrecision>",
                param->name().data());
            mPrecisionFailed = true;
        }
    }
}

bool ValidateAST::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
{
    visitNode(visit, node);

    if (mOptions.validateVariableReferences && visit == PreVisit)
    {
        const TFunction *function = node->getFunction();

        size_t paramCount = function->getParamCount();
        for (size_t paramIndex = 0; paramIndex < paramCount; ++paramIndex)
        {
            const TVariable *variable = function->getParam(paramIndex);

            if (isVariableDeclared(variable))
            {
                mDiagnostics->error(node->getLine(),
                                    "Found two declarations of the same function argument "
                                    "<validateVariableReferences>",
                                    variable->name().data());
                mVariableReferencesFailed = true;
                break;
            }

            mDeclaredVariables.back().insert(variable);
        }
    }

    return true;
}

bool ValidateAST::visitAggregate(Visit visit, TIntermAggregate *node)
{
    visitNode(visit, node);
    expectNonNullChildren(visit, node, 0);

    if (visit == PreVisit && mOptions.validateBuiltInOps)
    {
        visitBuiltInFunction(node, node->getFunction());
    }

    if (visit == PreVisit && mOptions.validateFunctionCall)
    {
        visitFunctionCall(node);
    }

    if (visit == PreVisit && mOptions.validateNoRawFunctionCalls)
    {
        if (node->getOp() == EOpCallInternalRawFunction)
        {
            mDiagnostics->error(node->getLine(),
                                "Found node calling a raw function (deprecated) "
                                "<validateNoRawFunctionCalls>",
                                node->getFunction()->name().data());
            mNoRawFunctionCallsFailed = true;
        }
    }

    if (visit == PreVisit && mOptions.validateNoQualifiersOnConstructors)
    {
        if (node->getOp() == EOpConstruct)
        {
            if (node->getType().isInvariant())
            {
                mDiagnostics->error(node->getLine(), "Found constructor node with invariant type",
                                    "<validateNoQualifiersOnConstructors>");
                mNoQualifiersOnConstructorsFailed = true;
            }
            if (node->getType().isPrecise())
            {
                mDiagnostics->error(node->getLine(), "Found constructor node with precise type",
                                    "<validateNoQualifiersOnConstructors>");
                mNoQualifiersOnConstructorsFailed = true;
            }
            if (node->getType().isInterpolant())
            {
                mDiagnostics->error(node->getLine(), "Found constructor node with interpolant type",
                                    "<validateNoQualifiersOnConstructors>");
                mNoQualifiersOnConstructorsFailed = true;
            }
            if (!node->getType().getMemoryQualifier().isEmpty())
            {
                mDiagnostics->error(node->getLine(),
                                    "Found constructor node whose type has a memory qualifier",
                                    "<validateNoQualifiersOnConstructors>");
                mNoQualifiersOnConstructorsFailed = true;
            }
            if (node->getType().getInterfaceBlock() != nullptr)
            {
                mDiagnostics->error(
                    node->getLine(),
                    "Found constructor node whose type references an interface block",
                    "<validateNoQualifiersOnConstructors>");
                mNoQualifiersOnConstructorsFailed = true;
            }
            if (!node->getType().getLayoutQualifier().isEmpty())
            {
                mDiagnostics->error(node->getLine(),
                                    "Found constructor node whose type has a layout qualifier",
                                    "<validateNoQualifiersOnConstructors>");
                mNoQualifiersOnConstructorsFailed = true;
            }
        }
    }

    return true;
}

bool ValidateAST::visitBlock(Visit visit, TIntermBlock *node)
{
    visitNode(visit, node);
    scope(visit);
    expectNonNullChildren(visit, node, 0);

    if (visit == PostVisit)
    {
        // If the parent is a block and mIsBranchVisitedInBlock is set, this is a nested block
        // without any condition (like if, loop or switch), so the rest of the parent block is also
        // dead code.  Otherwise the parent block can contain code after this.
        if (getParentNode() == nullptr || getParentNode()->getAsBlock() == nullptr)
        {
            mIsBranchVisitedInBlock = false;
        }
    }

    return true;
}

bool ValidateAST::visitGlobalQualifierDeclaration(Visit visit,
                                                  TIntermGlobalQualifierDeclaration *node)
{
    visitNode(visit, node);

    const TVariable *variable = &node->getSymbol()->variable();

    if (mOptions.validateVariableReferences && variableNeedsDeclaration(variable))
    {
        if (!isVariableDeclared(variable))
        {
            mDiagnostics->error(node->getLine(),
                                "Found reference to undeclared or inconsistently transformed "
                                "variable <validateVariableReferences>",
                                variable->name().data());
            mVariableReferencesFailed = true;
        }
    }
    return true;
}

bool ValidateAST::visitDeclaration(Visit visit, TIntermDeclaration *node)
{
    visitNode(visit, node);
    expectNonNullChildren(visit, node, 0);

    const TIntermSequence &sequence = *(node->getSequence());

    if (mOptions.validateMultiDeclarations && sequence.size() > 1)
    {
        TIntermSymbol *symbol = sequence[1]->getAsSymbolNode();
        if (symbol == nullptr)
        {
            TIntermBinary *init = sequence[1]->getAsBinaryNode();
            ASSERT(init && init->getOp() == EOpInitialize);
            symbol = init->getLeft()->getAsSymbolNode();
        }
        ASSERT(symbol);

        mDiagnostics->error(node->getLine(),
                            "Found multiple declarations where SeparateDeclarations should have "
                            "separated them <validateMultiDeclarations>",
                            symbol->variable().name().data());
        mMultiDeclarationsFailed = true;
    }

    if (visit == PreVisit)
    {
        bool validateStructUsage = mOptions.validateStructUsage;

        for (TIntermNode *instance : sequence)
        {
            TIntermSymbol *symbol = instance->getAsSymbolNode();
            if (symbol == nullptr)
            {
                TIntermBinary *init = instance->getAsBinaryNode();
                ASSERT(init && init->getOp() == EOpInitialize);
                symbol = init->getLeft()->getAsSymbolNode();
            }
            ASSERT(symbol);

            const TVariable *variable = &symbol->variable();
            const TType &type         = variable->getType();

            if (mOptions.validateVariableReferences)
            {
                if (isVariableDeclared(variable))
                {
                    mDiagnostics->error(
                        node->getLine(),
                        "Found two declarations of the same variable <validateVariableReferences>",
                        variable->name().data());
                    mVariableReferencesFailed = true;
                    break;
                }

                mDeclaredVariables.back().insert(variable);

                const TInterfaceBlock *interfaceBlock = variable->getType().getInterfaceBlock();

                if (variable->symbolType() == SymbolType::Empty && interfaceBlock != nullptr)
                {
                    // Nameless interface blocks can only be declared at the top level.  Their
                    // fields are matched by field index, and then verified to match by name.
                    // Conflict in names should have already generated a compile error.
                    ASSERT(mDeclaredVariables.size() == 1);
                    ASSERT(mNamelessInterfaceBlocks.count(interfaceBlock) == 0);

                    mNamelessInterfaceBlocks.insert(interfaceBlock);
                }
            }

            if (validateStructUsage)
            {
                // Only declare and/or validate the struct once.
                validateStructUsage = false;

                if (type.isStructSpecifier() || type.isInterfaceBlock())
                {
                    visitStructOrInterfaceBlockDeclaration(type, node->getLine());
                }
                else
                {
                    visitStructUsage(type, node->getLine());
                }
            }

            if (gl::IsBuiltInName(variable->name().data()))
            {
                visitBuiltInVariable(symbol);
            }

            if (mOptions.validatePrecision && (type.isStructSpecifier() || type.isInterfaceBlock()))
            {
                const TFieldListCollection *structOrBlock = type.getStruct();
                if (structOrBlock == nullptr)
                {
                    structOrBlock = type.getInterfaceBlock();
                }

                for (const TField *field : structOrBlock->fields())
                {
                    const TType *fieldType = field->type();
                    if (IsPrecisionApplicableToType(fieldType->getBasicType()) &&
                        fieldType->getPrecision() == EbpUndefined)
                    {
                        mDiagnostics->error(
                            node->getLine(),
                            "Found block field with undefined precision <validatePrecision>",
                            field->name().data());
                        mPrecisionFailed = true;
                    }
                }
            }
        }
    }

    return true;
}

bool ValidateAST::visitLoop(Visit visit, TIntermLoop *node)
{
    visitNode(visit, node);
    return true;
}

bool ValidateAST::visitBranch(Visit visit, TIntermBranch *node)
{
    visitNode(visit, node);

    if (visit == PreVisit && mOptions.validateOps)
    {
        const TOperator op = node->getFlowOp();
        if (!IsBranchOp(op))
        {
            mDiagnostics->error(node->getLine(),
                                "Found branch node with non-branch op <validateOps>",
                                GetOperatorString(op));
            mOpsFailed = true;
        }
    }
    if (visit == PostVisit)
    {
        mIsBranchVisitedInBlock = true;
    }

    return true;
}

void ValidateAST::visitPreprocessorDirective(TIntermPreprocessorDirective *node)
{
    visitNode(PreVisit, node);
}

bool ValidateAST::validateInternal()
{
    return !mSingleParentFailed && !mVariableReferencesFailed && !mOpsFailed &&
           !mBuiltInOpsFailed && !mFunctionCallFailed && !mNoRawFunctionCallsFailed &&
           !mNullNodesFailed && !mQualifiersFailed && !mPrecisionFailed && !mStructUsageFailed &&
           !mExpressionTypesFailed && !mMultiDeclarationsFailed && !mNoSwizzleOfSwizzleFailed &&
           !mNoQualifiersOnConstructorsFailed && !mNoStatementsAfterBranchFailed &&
           !mVariableNamingFailed;
}

bool ValidateAST::isInDeclaration() const
{
    auto *parent = getParentNode();
    return parent != nullptr && parent->getAsDeclarationNode() != nullptr;
}

}  // anonymous namespace

bool ValidateAST(TIntermNode *root, TDiagnostics *diagnostics, const ValidateASTOptions &options)
{
    // ValidateAST is called after transformations, so if |validateNoMoreTransformations| is set,
    // it's immediately an error.
    if (options.validateNoMoreTransformations)
    {
        diagnostics->error(kNoSourceLoc, "Unexpected transformation after AST post-processing",
                           "<validateNoMoreTransformations>");
        return false;
    }

    return ValidateAST::validate(root, diagnostics, options);
}

}  // namespace sh
