Commit fcad1bfd by Nicolas Capens

Fix short-circuiting in preprocessor.

The 2nd operand in a logical and ('&&') operation is evaluated if and only if the 1st operand evaluates to non-zero. The 2nd operand in a logical or ('||') operation is evaluated if and only if the 1st operand evaluates to zero. If an operand is not evaluated, the presence of undefined identifiers in the operand will not cause an error. Integer overflow in short-circuited expressions are still and error because it is part of lexical analysis. Change-Id: I6ff5e0e9874551d2e40ab4e4ad34dc36cfa703e5 Reviewed-on: https://swiftshader-review.googlesource.com/5020Tested-by: 's avatarNicolas Capens <capn@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <capn@google.com>
parent 7bd3d395
...@@ -52,6 +52,7 @@ struct Context ...@@ -52,6 +52,7 @@ struct Context
pp::Lexer* lexer; pp::Lexer* lexer;
pp::Token* token; pp::Token* token;
int* result; int* result;
int shortCircuited; // Don't produce errors when > 0
}; };
} // namespace } // namespace
%} %}
...@@ -90,11 +91,37 @@ input ...@@ -90,11 +91,37 @@ input
expression expression
: TOK_CONST_INT : TOK_CONST_INT
| expression TOK_OP_OR expression { | expression TOK_OP_OR {
$$ = $1 || $3; if ($1 != 0)
{
context->shortCircuited++;
}
} expression {
if ($1 != 0)
{
context->shortCircuited--;
$$ = 1;
}
else
{
$$ = $1 || $4;
}
}
| expression TOK_OP_AND {
if ($1 == 0)
{
context->shortCircuited++;
}
} expression {
if ($1 == 0)
{
context->shortCircuited--;
$$ = 0;
}
else
{
$$ = $1 && $4;
} }
| expression TOK_OP_AND expression {
$$ = $1 && $3;
} }
| expression '|' expression { | expression '|' expression {
$$ = $1 | $3; $$ = $1 | $3;
...@@ -136,20 +163,40 @@ expression ...@@ -136,20 +163,40 @@ expression
$$ = $1 + $3; $$ = $1 + $3;
} }
| expression '%' expression { | expression '%' expression {
if ($3 == 0) { if ($3 == 0)
{
if (!context->shortCircuited)
{
context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO, context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO,
context->token->location, ""); context->token->location, "");
YYABORT; YYABORT;
} else { }
else
{
$$ = 0;
}
}
else
{
$$ = $1 % $3; $$ = $1 % $3;
} }
} }
| expression '/' expression { | expression '/' expression {
if ($3 == 0) { if ($3 == 0)
{
if (!context->shortCircuited)
{
context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO, context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO,
context->token->location, ""); context->token->location, "");
YYABORT; YYABORT;
} else { }
else
{
$$ = 0;
}
}
else
{
$$ = $1 / $3; $$ = $1 / $3;
} }
} }
...@@ -195,11 +242,14 @@ int yylex(YYSTYPE* lvalp, Context* context) ...@@ -195,11 +242,14 @@ int yylex(YYSTYPE* lvalp, Context* context)
break; break;
} }
case pp::Token::IDENTIFIER: case pp::Token::IDENTIFIER:
if (!context->shortCircuited)
{
// Defined identifiers should have been expanded already. // Defined identifiers should have been expanded already.
// Unlike the C/C++ preprocessor, it does not default to 0. // Unlike the C/C++ preprocessor, it does not default to 0.
// Use of such identifiers causes an error. // Use of such identifiers causes an error.
context->diagnostics->report(pp::Diagnostics::UNDEFINED_IDENTIFIER, context->diagnostics->report(pp::Diagnostics::UNDEFINED_IDENTIFIER,
token->location, token->text); token->location, token->text);
}
*lvalp = 0; *lvalp = 0;
type = TOK_CONST_INT; type = TOK_CONST_INT;
...@@ -258,6 +308,7 @@ bool ExpressionParser::parse(Token* token, int* result) ...@@ -258,6 +308,7 @@ bool ExpressionParser::parse(Token* token, int* result)
context.lexer = mLexer; context.lexer = mLexer;
context.token = token; context.token = token;
context.result = result; context.result = result;
context.shortCircuited = 0;
int ret = yyparse(&context); int ret = yyparse(&context);
switch (ret) switch (ret)
{ {
......
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