| // | |
| // Copyright (c) 2002-2015 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 "ValidateGlobalInitializer.h" | |
| #include "ParseHelper.h" | |
| namespace | |
| { | |
| class ValidateGlobalInitializerTraverser : public TIntermTraverser | |
| { | |
| public: | |
| ValidateGlobalInitializerTraverser(const TParseContext *context); | |
| void visitSymbol(TIntermSymbol *node) override; | |
| bool isValid() const { return mIsValid; } | |
| bool issueWarning() const { return mIssueWarning; } | |
| private: | |
| const TParseContext *mContext; | |
| bool mIsValid; | |
| bool mIssueWarning; | |
| }; | |
| void ValidateGlobalInitializerTraverser::visitSymbol(TIntermSymbol *node) | |
| { | |
| const TSymbol *sym = mContext->symbolTable.find(node->getSymbol(), mContext->getShaderVersion()); | |
| if (sym->isVariable()) | |
| { | |
| // ESSL 1.00 section 4.3 (or ESSL 3.00 section 4.3): | |
| // Global initializers must be constant expressions. | |
| const TVariable *var = static_cast<const TVariable *>(sym); | |
| switch (var->getType().getQualifier()) | |
| { | |
| case EvqConstExpr: | |
| break; | |
| case EvqGlobal: | |
| case EvqTemporary: | |
| case EvqUniform: | |
| // We allow these cases to be compatible with legacy ESSL 1.00 content. | |
| // Implement stricter rules for ESSL 3.00 since there's no legacy content to deal with. | |
| if (mContext->getShaderVersion() >= 300) | |
| { | |
| mIsValid = false; | |
| } | |
| else | |
| { | |
| mIssueWarning = true; | |
| } | |
| break; | |
| default: | |
| mIsValid = false; | |
| } | |
| } | |
| } | |
| ValidateGlobalInitializerTraverser::ValidateGlobalInitializerTraverser(const TParseContext *context) | |
| : TIntermTraverser(true, false, false), | |
| mContext(context), | |
| mIsValid(true), | |
| mIssueWarning(false) | |
| { | |
| } | |
| } // namespace | |
| bool ValidateGlobalInitializer(TIntermTyped *initializer, const TParseContext *context, bool *warning) | |
| { | |
| ValidateGlobalInitializerTraverser validate(context); | |
| initializer->traverse(&validate); | |
| ASSERT(warning != nullptr); | |
| *warning = validate.issueWarning(); | |
| return validate.isValid(); | |
| } | |