Commit 8162926b by Olli Etuaho Committed by Commit Bot

Never add declarations without children to the AST

When block nodes were being created for loop bodies that didn't have braces in the parsed source, the code didn't check if the loop body was a declaration node without children. Always use appendStatement() for adding statements to a block, so that declaration nodes without children don't end up in the AST. Similarly make sure that loop init nodes aren't declarations without children. BUG=chromium:712550 TEST=angle_end2end_tests Change-Id: I5e79b700fe6158fa2422fcf4cd13818b2bd24863 Reviewed-on: https://chromium-review.googlesource.com/481660Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent 0c0dc345
......@@ -1028,6 +1028,22 @@ TIntermTernary::TIntermTernary(TIntermTyped *cond,
TIntermTernary::DetermineQualifier(cond, trueExpression, falseExpression));
}
TIntermLoop::TIntermLoop(TLoopType type,
TIntermNode *init,
TIntermTyped *cond,
TIntermTyped *expr,
TIntermBlock *body)
: mType(type), mInit(init), mCond(cond), mExpr(expr), mBody(body)
{
// Declaration nodes with no children can appear if all the declarators just added constants to
// the symbol table instead of generating code. They're no-ops so don't add them to the tree.
if (mInit && mInit->getAsDeclarationNode() &&
mInit->getAsDeclarationNode()->getSequence()->empty())
{
mInit = nullptr;
}
}
// static
TQualifier TIntermTernary::DetermineQualifier(TIntermTyped *cond,
TIntermTyped *trueExpression,
......
......@@ -204,10 +204,7 @@ class TIntermLoop : public TIntermNode
TIntermNode *init,
TIntermTyped *cond,
TIntermTyped *expr,
TIntermBlock *body)
: mType(type), mInit(init), mCond(cond), mExpr(expr), mBody(body)
{
}
TIntermBlock *body);
TIntermLoop *getAsLoopNode() override { return this; }
void traverse(TIntermTraverser *it) override;
......
......@@ -80,7 +80,7 @@ TIntermBlock *TIntermediate::EnsureBlock(TIntermNode *node)
blockNode = new TIntermBlock();
blockNode->setLine(node->getLine());
blockNode->getSequence()->push_back(node);
blockNode->appendStatement(node);
return blockNode;
}
......
......@@ -2770,6 +2770,37 @@ TEST_P(GLSLTest_ES3, NestedSamplingOperation)
EXPECT_PIXEL_COLOR_EQ_VEC2(lr, simpleColors[3]);
}
// Tests that using a constant declaration as the only statement in a for loop without curly braces
// doesn't crash.
TEST_P(GLSLTest, ConstantStatementInForLoop)
{
const std::string &vertexShader =
"void main()\n"
"{\n"
" for (int i = 0; i < 10; ++i)\n"
" const int b = 0;\n"
"}\n";
GLuint shader = CompileShader(GL_VERTEX_SHADER, vertexShader);
EXPECT_NE(0u, shader);
glDeleteShader(shader);
}
// Tests that using a constant declaration as a loop init expression doesn't crash. Note that this
// test doesn't work on D3D9 due to looping limitations, so it is only run on ES3.
TEST_P(GLSLTest_ES3, ConstantStatementAsLoopInit)
{
const std::string &vertexShader =
"void main()\n"
"{\n"
" for (const int i = 0; i < 0;) {}\n"
"}\n";
GLuint shader = CompileShader(GL_VERTEX_SHADER, vertexShader);
EXPECT_NE(0u, shader);
glDeleteShader(shader);
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
ANGLE_INSTANTIATE_TEST(GLSLTest,
ES2_D3D9(),
......
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