diff options
Diffstat (limited to 'src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp')
-rw-r--r-- | src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp | 179 |
1 files changed, 149 insertions, 30 deletions
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp index 9a4ed33632..9f7a264e58 100644 --- a/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp @@ -6,21 +6,76 @@ #include "compiler/translator/ValidateSwitch.h" -#include "compiler/translator/ParseContext.h" +#include "compiler/translator/Diagnostics.h" +#include "compiler/translator/IntermTraverse.h" -bool ValidateSwitch::validate(TBasicType switchType, TParseContext *context, - TIntermAggregate *statementList, const TSourceLoc &loc) +namespace sh { - ValidateSwitch validate(switchType, context); + +namespace +{ + +class ValidateSwitch : public TIntermTraverser +{ + public: + static bool validate(TBasicType switchType, + int shaderVersion, + TDiagnostics *diagnostics, + TIntermBlock *statementList, + const TSourceLoc &loc); + + void visitSymbol(TIntermSymbol *) override; + void visitConstantUnion(TIntermConstantUnion *) override; + bool visitDeclaration(Visit, TIntermDeclaration *) override; + bool visitBlock(Visit, TIntermBlock *) override; + bool visitBinary(Visit, TIntermBinary *) override; + bool visitUnary(Visit, TIntermUnary *) override; + bool visitTernary(Visit, TIntermTernary *) override; + bool visitSwizzle(Visit, TIntermSwizzle *) override; + bool visitIfElse(Visit visit, TIntermIfElse *) override; + bool visitSwitch(Visit, TIntermSwitch *) override; + bool visitCase(Visit, TIntermCase *node) override; + bool visitAggregate(Visit, TIntermAggregate *) override; + bool visitLoop(Visit visit, TIntermLoop *) override; + bool visitBranch(Visit, TIntermBranch *) override; + + private: + ValidateSwitch(TBasicType switchType, int shaderVersion, TDiagnostics *context); + + bool validateInternal(const TSourceLoc &loc); + + TBasicType mSwitchType; + int mShaderVersion; + TDiagnostics *mDiagnostics; + bool mCaseTypeMismatch; + bool mFirstCaseFound; + bool mStatementBeforeCase; + bool mLastStatementWasCase; + int mControlFlowDepth; + bool mCaseInsideControlFlow; + int mDefaultCount; + std::set<int> mCasesSigned; + std::set<unsigned int> mCasesUnsigned; + bool mDuplicateCases; +}; + +bool ValidateSwitch::validate(TBasicType switchType, + int shaderVersion, + TDiagnostics *diagnostics, + TIntermBlock *statementList, + const TSourceLoc &loc) +{ + ValidateSwitch validate(switchType, shaderVersion, diagnostics); ASSERT(statementList); statementList->traverse(&validate); return validate.validateInternal(loc); } -ValidateSwitch::ValidateSwitch(TBasicType switchType, TParseContext *context) +ValidateSwitch::ValidateSwitch(TBasicType switchType, int shaderVersion, TDiagnostics *diagnostics) : TIntermTraverser(true, false, true), mSwitchType(switchType), - mContext(context), + mShaderVersion(shaderVersion), + mDiagnostics(diagnostics), mCaseTypeMismatch(false), mFirstCaseFound(false), mStatementBeforeCase(false), @@ -29,13 +84,14 @@ ValidateSwitch::ValidateSwitch(TBasicType switchType, TParseContext *context) mCaseInsideControlFlow(false), mDefaultCount(0), mDuplicateCases(false) -{} +{ +} void ValidateSwitch::visitSymbol(TIntermSymbol *) { if (!mFirstCaseFound) mStatementBeforeCase = true; - mLastStatementWasCase = false; + mLastStatementWasCase = false; } void ValidateSwitch::visitConstantUnion(TIntermConstantUnion *) @@ -44,14 +100,33 @@ void ValidateSwitch::visitConstantUnion(TIntermConstantUnion *) // Could be just a statement like "0;" if (!mFirstCaseFound) mStatementBeforeCase = true; - mLastStatementWasCase = false; + mLastStatementWasCase = false; +} + +bool ValidateSwitch::visitDeclaration(Visit, TIntermDeclaration *) +{ + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + return true; +} + +bool ValidateSwitch::visitBlock(Visit, TIntermBlock *) +{ + if (getParentNode() != nullptr) + { + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + } + return true; } bool ValidateSwitch::visitBinary(Visit, TIntermBinary *) { if (!mFirstCaseFound) mStatementBeforeCase = true; - mLastStatementWasCase = false; + mLastStatementWasCase = false; return true; } @@ -59,11 +134,27 @@ bool ValidateSwitch::visitUnary(Visit, TIntermUnary *) { if (!mFirstCaseFound) mStatementBeforeCase = true; - mLastStatementWasCase = false; + mLastStatementWasCase = false; + return true; +} + +bool ValidateSwitch::visitTernary(Visit, TIntermTernary *) +{ + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + return true; +} + +bool ValidateSwitch::visitSwizzle(Visit, TIntermSwizzle *) +{ + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; return true; } -bool ValidateSwitch::visitSelection(Visit visit, TIntermSelection *) +bool ValidateSwitch::visitIfElse(Visit visit, TIntermIfElse *) { if (visit == PreVisit) ++mControlFlowDepth; @@ -71,7 +162,7 @@ bool ValidateSwitch::visitSelection(Visit visit, TIntermSelection *) --mControlFlowDepth; if (!mFirstCaseFound) mStatementBeforeCase = true; - mLastStatementWasCase = false; + mLastStatementWasCase = false; return true; } @@ -79,7 +170,7 @@ bool ValidateSwitch::visitSwitch(Visit, TIntermSwitch *) { if (!mFirstCaseFound) mStatementBeforeCase = true; - mLastStatementWasCase = false; + mLastStatementWasCase = false; // Don't go into nested switch statements return false; } @@ -89,17 +180,17 @@ bool ValidateSwitch::visitCase(Visit, TIntermCase *node) const char *nodeStr = node->hasCondition() ? "case" : "default"; if (mControlFlowDepth > 0) { - mContext->error(node->getLine(), "label statement nested inside control flow", nodeStr); + mDiagnostics->error(node->getLine(), "label statement nested inside control flow", nodeStr); mCaseInsideControlFlow = true; } - mFirstCaseFound = true; + mFirstCaseFound = true; mLastStatementWasCase = true; if (!node->hasCondition()) { ++mDefaultCount; if (mDefaultCount > 1) { - mContext->error(node->getLine(), "duplicate default label", nodeStr); + mDiagnostics->error(node->getLine(), "duplicate default label", nodeStr); } } else @@ -113,8 +204,9 @@ bool ValidateSwitch::visitCase(Visit, TIntermCase *node) TBasicType conditionType = condition->getBasicType(); if (conditionType != mSwitchType) { - mContext->error(condition->getLine(), - "case label type does not match switch init-expression type", nodeStr); + mDiagnostics->error(condition->getLine(), + "case label type does not match switch init-expression type", + nodeStr); mCaseTypeMismatch = true; } @@ -123,7 +215,7 @@ bool ValidateSwitch::visitCase(Visit, TIntermCase *node) int iConst = condition->getIConst(0); if (mCasesSigned.find(iConst) != mCasesSigned.end()) { - mContext->error(condition->getLine(), "duplicate case label", nodeStr); + mDiagnostics->error(condition->getLine(), "duplicate case label", nodeStr); mDuplicateCases = true; } else @@ -136,7 +228,7 @@ bool ValidateSwitch::visitCase(Visit, TIntermCase *node) unsigned int uConst = condition->getUConst(0); if (mCasesUnsigned.find(uConst) != mCasesUnsigned.end()) { - mContext->error(condition->getLine(), "duplicate case label", nodeStr); + mDiagnostics->error(condition->getLine(), "duplicate case label", nodeStr); mDuplicateCases = true; } else @@ -158,7 +250,7 @@ bool ValidateSwitch::visitAggregate(Visit visit, TIntermAggregate *) // This is not the statementList node, but some other node. if (!mFirstCaseFound) mStatementBeforeCase = true; - mLastStatementWasCase = false; + mLastStatementWasCase = false; } return true; } @@ -171,7 +263,7 @@ bool ValidateSwitch::visitLoop(Visit visit, TIntermLoop *) --mControlFlowDepth; if (!mFirstCaseFound) mStatementBeforeCase = true; - mLastStatementWasCase = false; + mLastStatementWasCase = false; return true; } @@ -179,7 +271,7 @@ bool ValidateSwitch::visitBranch(Visit, TIntermBranch *) { if (!mFirstCaseFound) mStatementBeforeCase = true; - mLastStatementWasCase = false; + mLastStatementWasCase = false; return true; } @@ -187,14 +279,41 @@ bool ValidateSwitch::validateInternal(const TSourceLoc &loc) { if (mStatementBeforeCase) { - mContext->error(loc, - "statement before the first label", "switch"); + mDiagnostics->error(loc, "statement before the first label", "switch"); } + bool lastStatementWasCaseError = false; if (mLastStatementWasCase) { - mContext->error(loc, - "no statement between the last label and the end of the switch statement", "switch"); + if (mShaderVersion == 300) + { + lastStatementWasCaseError = true; + // This error has been proposed to be made optional in GLSL ES 3.00, but dEQP tests + // still require it. + mDiagnostics->error( + loc, "no statement between the last label and the end of the switch statement", + "switch"); + } + else + { + // The error has been removed from GLSL ES 3.10. + mDiagnostics->warning( + loc, "no statement between the last label and the end of the switch statement", + "switch"); + } } - return !mStatementBeforeCase && !mLastStatementWasCase && !mCaseInsideControlFlow && - !mCaseTypeMismatch && mDefaultCount <= 1 && !mDuplicateCases; + return !mStatementBeforeCase && !lastStatementWasCaseError && !mCaseInsideControlFlow && + !mCaseTypeMismatch && mDefaultCount <= 1 && !mDuplicateCases; +} + +} // anonymous namespace + +bool ValidateSwitchStatementList(TBasicType switchType, + int shaderVersion, + TDiagnostics *diagnostics, + TIntermBlock *statementList, + const TSourceLoc &loc) +{ + return ValidateSwitch::validate(switchType, shaderVersion, diagnostics, statementList, loc); } + +} // namespace sh |