Commit b8ee9dd3 by Olli Etuaho Committed by Commit Bot

Validate empty statements in switch statements

Even an empty statement like ";" is a statement according to the grammar. They should not be allowed in switch statements before the first case statement, but on the other hand a switch statement that has just an empty statement after the last statement is valid. Now the parser creates AST nodes from empty statements so that we can validate switch statements correctly. However, they are pruned shortly after parsing completes in PruneNoOps, so they don't affect further processing of the AST. BUG=angleproject:2181 TEST=angle_unittests Change-Id: I1085056fc34b146142546fc5f2b7f3124b910ab9 Reviewed-on: https://chromium-review.googlesource.com/743621Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent 1b605ee3
......@@ -2701,6 +2701,15 @@ void TParseContext::parseArrayInitDeclarator(const TPublicType &elementType,
}
}
TIntermNode *TParseContext::addEmptyStatement(const TSourceLoc &location)
{
// It's simpler to parse an empty statement as a constant expression rather than having a
// different type of node just for empty statements, that will be pruned from the AST anyway.
TIntermNode *node = CreateZeroNode(TType(EbtInt, EbpMedium));
node->setLine(location);
return node;
}
void TParseContext::setAtomicCounterBindingDefaultOffset(const TPublicType &publicType,
const TSourceLoc &location)
{
......
......@@ -262,6 +262,8 @@ class TParseContext : angle::NonCopyable
TIntermTyped *initializer,
TIntermDeclaration *declarationOut);
TIntermNode *addEmptyStatement(const TSourceLoc &location);
void parseDefaultPrecisionQualifier(const TPrecision precision,
const TPublicType &type,
const TSourceLoc &loc);
......
......@@ -1293,7 +1293,7 @@ statement_list
;
expression_statement
: SEMICOLON { $$ = 0; }
: SEMICOLON { $$ = context->addEmptyStatement(@$); }
| expression SEMICOLON { $$ = $1; }
;
......
......@@ -4591,7 +4591,7 @@ yyreduce:
case 262:
{ (yyval.interm.intermNode) = 0; }
{ (yyval.interm.intermNode) = context->addEmptyStatement((yyloc)); }
break;
......
......@@ -5194,3 +5194,31 @@ TEST_F(FragmentShaderValidationTest, DuplicateFieldNamesInStructDeclaratorList)
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
// Test that an empty statement is not allowed in switch before the first case.
TEST_F(FragmentShaderValidationTest, EmptyStatementInSwitchBeforeFirstCase)
{
const std::string &shaderString =
R"(#version 300 es
precision mediump float;
uniform int u_zero;
out vec4 my_FragColor;
void main()
{
switch(u_zero)
{
;
case 0:
my_FragColor = vec4(0.0);
default:
my_FragColor = vec4(1.0);
}
})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
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