Commit 0e07119a by John Kessenich

HLSL: Fix #919: for-init-statement is arbitrary declaration or expression.

Unlike "if (XXX)" and "while (XXX)", with "for (YYY...", the YYY can be more kinds of statements than the XXX.
parent e00e8f45
......@@ -5,9 +5,13 @@ float4 PixelShaderFunction(float4 input) : COLOR0
[unroll] for (; any(input != input); ) {}
for (; any(input != input); ) { return -input; }
for (--input; any(input != input); input += 2) { return -input; }
for (;;) if (input.x > 2.0) break;
for (;;) if (input.x > 2.0) continue;
float ii;
for (int ii = -1; ii < 3; ++ii) if (ii == 2) continue;
--ii;
for (;;) if (input.x > 2.0) break;
for (;;) if (input.x > 2.0) continue;
float ii;
for (int ii = -1; ii < 3; ++ii) if (ii == 2) continue;
--ii;
for (int first = 0, second = 1; ;) first + second;
for ( int i = 0, count = int(ii); i < count; i++ );
for (float first = 0, second[2], third; first < second[0]; ++second[1]) first + second[1] + third;
for (--ii, --ii, --ii;;) ii;
}
......@@ -1735,8 +1735,13 @@ TIntermAggregate* TIntermediate::addForLoop(TIntermNode* body, TIntermNode* init
node->setLoc(loc);
node->setLoopControl(control);
// make a sequence of the initializer and statement
TIntermAggregate* loopSequence = makeAggregate(initializer, loc);
// make a sequence of the initializer and statement, but try to reuse the
// aggregate already created for whatever is in the initializer, if there is one
TIntermAggregate* loopSequence = (initializer == nullptr ||
initializer->getAsAggregate() == nullptr) ? makeAggregate(initializer, loc)
: initializer->getAsAggregate();
if (loopSequence != nullptr && loopSequence->getOp() == EOpSequence)
loopSequence->setOp(EOpNull);
loopSequence = growAggregate(loopSequence, node);
loopSequence->setOperator(EOpSequence);
......
......@@ -3039,6 +3039,37 @@ bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
return true;
}
// simple_statement
// : SEMICOLON
// | declaration_statement
// | expression SEMICOLON
//
bool HlslGrammar::acceptSimpleStatement(TIntermNode*& statement)
{
// SEMICOLON
if (acceptTokenClass(EHTokSemicolon))
return true;
// declaration
if (acceptDeclaration(statement))
return true;
// expression
TIntermTyped* node;
if (acceptExpression(node))
statement = node;
else
return false;
// SEMICOLON (following an expression)
if (acceptTokenClass(EHTokSemicolon))
return true;
else {
expected(";");
return false;
}
}
// compound_statement
// : LEFT_CURLY statement statement ... RIGHT_CURLY
//
......@@ -3096,12 +3127,11 @@ bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
//
// attributed_statement
// : compound_statement
// | SEMICOLON
// | expression SEMICOLON
// | declaration_statement
// | simple_statement
// | selection_statement
// | switch_statement
// | case_label
// | default_label
// | iteration_statement
// | jump_statement
//
......@@ -3140,33 +3170,13 @@ bool HlslGrammar::acceptStatement(TIntermNode*& statement)
case EHTokDefault:
return acceptDefaultLabel(statement);
case EHTokSemicolon:
return acceptTokenClass(EHTokSemicolon);
case EHTokRightBrace:
// Performance: not strictly necessary, but stops a bunch of hunting early,
// and is how sequences of statements end.
return false;
default:
{
// declaration
if (acceptDeclaration(statement))
return true;
// expression
TIntermTyped* node;
if (acceptExpression(node))
statement = node;
else
return false;
// SEMICOLON (following an expression)
if (! acceptTokenClass(EHTokSemicolon)) {
expected(";");
return false;
}
}
return acceptSimpleStatement(statement);
}
return true;
......@@ -3420,14 +3430,8 @@ bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttri
// initializer
TIntermNode* initNode = nullptr;
if (! acceptControlDeclaration(initNode)) {
TIntermTyped* initExpr = nullptr;
acceptExpression(initExpr);
initNode = initExpr;
}
// SEMI_COLON
if (! acceptTokenClass(EHTokSemicolon))
expected(";");
if (! acceptSimpleStatement(initNode))
expected("for-loop initializer statement");
parseContext.nestLooping();
......
......@@ -108,10 +108,11 @@ namespace glslang {
bool acceptFunctionCall(const TSourceLoc&, TString& name, TIntermTyped*&, TIntermTyped* objectBase);
bool acceptArguments(TFunction*, TIntermTyped*&);
bool acceptLiteral(TIntermTyped*&);
bool acceptSimpleStatement(TIntermNode*&);
bool acceptCompoundStatement(TIntermNode*&);
bool acceptStatement(TIntermNode*&);
bool acceptScopedStatement(TIntermNode*&);
bool acceptScopedCompoundStatement(TIntermNode*&);
bool acceptStatement(TIntermNode*&);
bool acceptNestedStatement(TIntermNode*&);
void acceptAttributes(TAttributeMap&);
bool acceptSelectionStatement(TIntermNode*&);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment