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

    // For validateNoCaseAtEndOfSwitchBlock:
    bool mNoCaseAtEndOfSwitchBlockFailed = 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;
    }

    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);
    }

    if (mOptions.validateNoCaseAtEndOfSwitchBlock && visit == PreVisit)
    {
        const TIntermSequence &statements = *node->getStatementList()->getSequence();
        if (!statements.empty() && statements.back()->getAsCaseNode() != nullptr)
        {
            mDiagnostics->error(node->getLine(), "Found switch block that ends in a case statement",
                                "<validateNoCaseAtEndOfSwitchBlock>");
            mNoCaseAtEndOfSwitchBlockFailed = true;
        }
    }

    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 &&
           !mNoCaseAtEndOfSwitchBlockFailed && !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
