See if this loop satisfies the limitations for ES 2.0 (version 100) for loops in Appendex A: "The loop index has type int or float. "The for statement has the form: for ( init-declaration ; condition ; expression ) init-declaration has the form: type-specifier identifier = constant-expression condition has the form: loop-index relational_operator constant-expression where relational_operator is
| 6509 | // The body is handled in an AST traversal. |
| 6510 | // |
| 6511 | void TParseContext::inductiveLoopCheck(const TSourceLoc& loc, TIntermNode* init, TIntermLoop* loop) |
| 6512 | { |
| 6513 | // loop index init must exist and be a declaration, which shows up in the AST as an aggregate of size 1 of the declaration |
| 6514 | bool badInit = false; |
| 6515 | if (! init || ! init->getAsAggregate() || init->getAsAggregate()->getSequence().size() != 1) |
| 6516 | badInit = true; |
| 6517 | TIntermBinary* binaryInit = nullptr; |
| 6518 | if (! badInit) { |
| 6519 | // get the declaration assignment |
| 6520 | binaryInit = init->getAsAggregate()->getSequence()[0]->getAsBinaryNode(); |
| 6521 | if (! binaryInit) |
| 6522 | badInit = true; |
| 6523 | } |
| 6524 | if (badInit) { |
| 6525 | error(loc, "inductive-loop init-declaration requires the form \"type-specifier loop-index = constant-expression\"", "limitations", ""); |
| 6526 | return; |
| 6527 | } |
| 6528 | |
| 6529 | // loop index must be type int or float |
| 6530 | if (! binaryInit->getType().isScalar() || (binaryInit->getBasicType() != EbtInt && binaryInit->getBasicType() != EbtFloat)) { |
| 6531 | error(loc, "inductive loop requires a scalar 'int' or 'float' loop index", "limitations", ""); |
| 6532 | return; |
| 6533 | } |
| 6534 | |
| 6535 | // init is the form "loop-index = constant" |
| 6536 | if (binaryInit->getOp() != EOpAssign || ! binaryInit->getLeft()->getAsSymbolNode() || ! binaryInit->getRight()->getAsConstantUnion()) { |
| 6537 | error(loc, "inductive-loop init-declaration requires the form \"type-specifier loop-index = constant-expression\"", "limitations", ""); |
| 6538 | return; |
| 6539 | } |
| 6540 | |
| 6541 | // get the unique id of the loop index |
| 6542 | long long loopIndex = binaryInit->getLeft()->getAsSymbolNode()->getId(); |
| 6543 | inductiveLoopIds.insert(loopIndex); |
| 6544 | |
| 6545 | // condition's form must be "loop-index relational-operator constant-expression" |
| 6546 | bool badCond = ! loop->getTestExpr(); |
| 6547 | if (! badCond) { |
| 6548 | TIntermBinary* binaryCond = loop->getTestExpr()->getAsBinaryNode(); |
| 6549 | badCond = ! binaryCond; |
| 6550 | if (! badCond) { |
| 6551 | switch (binaryCond->getOp()) { |
| 6552 | case EOpGreaterThan: |
| 6553 | case EOpGreaterThanEqual: |
| 6554 | case EOpLessThan: |
| 6555 | case EOpLessThanEqual: |
| 6556 | case EOpEqual: |
| 6557 | case EOpNotEqual: |
| 6558 | break; |
| 6559 | default: |
| 6560 | badCond = true; |
| 6561 | } |
| 6562 | } |
| 6563 | if (binaryCond && (! binaryCond->getLeft()->getAsSymbolNode() || |
| 6564 | binaryCond->getLeft()->getAsSymbolNode()->getId() != loopIndex || |
| 6565 | ! binaryCond->getRight()->getAsConstantUnion())) |
| 6566 | badCond = true; |
| 6567 | } |
| 6568 | if (badCond) { |
no test coverage detected