Commit 247374cb by Olli Etuaho

Allow limited form of expressions in #line directives

Reuse ExpressionParser that's also used for parsing preprocessor conditionals to parse line and file numbers in #line directives. According to recent Khronos discussions, the intent of the spec is that expressions in #line directives should be interpreted similarly to expressions in conditional directives, so reusing ExpressionParser is a natural way to implement this. This enables simple math operators operating on integers. There are a few unclear corner cases, but this approach is enough to support practical use cases and pass the dEQP tests. Valid line directives have one of the following forms: #line line-expression #line line-expression file-expression ExpressionParser is first run to parse the line-expression. In ambiguous cases the ExpressionParser consumes as much of the line as possible to form line-expression. Then, if end-of-line hasn't been reached, file-expression is parsed by running ExpressionParser again. As an example of an ambiguous case: #line 1 + 2 This could alternatively be interpreted to mean line-expression "1" and file-expression "+ 2" where + is the unary + operator, but ANGLE now interprets it to mean line-expression "1 + 2". Because of these ambiguous cases, a bison grammar that would parse multiple expressions on the same line couldn't be easily constructed, so this solution where ExpressionParser is run twice was chosen instead. The problematic corner cases are: - ExpressionParser uses 64-bit integers internally for evaluating the expression's value. It's possible to interpret the ESSL3 spec so that 32-bit integer wraparound behavior would be required also for #line directive expressions. - It's unclear whether the defined operator can be used in #line expressions. In this patch it is disabled. Hoping for further clarification from Khronos. - It's unclear how short-circuiting should affect the parsing of undefined identifiers in #line expressions. Now it's consistent with #if expressions (undefined identifiers are OK if they're short-circuited). dEQP expectations are updated for preprocessor tests, including ones not affected specifically by this change. BUG=angleproject:989 TEST=angle_unittests, dEQP-GLES3.functional.shaders.preprocessor.* (4 start passing), dEQP-GLES2.functional.shaders.preprocessor.* (4 start passing) Change-Id: I55c5bf75857da5de855cc600d3603ee19399f328 Reviewed-on: https://chromium-review.googlesource.com/300964Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Tryjob-Request: Olli Etuaho <oetuaho@nvidia.com> Tested-by: 's avatarOlli Etuaho <oetuaho@nvidia.com>
parent 412f17da
...@@ -764,72 +764,60 @@ void DirectiveParser::parseLine(Token *token) ...@@ -764,72 +764,60 @@ void DirectiveParser::parseLine(Token *token)
{ {
assert(getDirective(token) == DIRECTIVE_LINE); assert(getDirective(token) == DIRECTIVE_LINE);
enum State
{
LINE_NUMBER,
FILE_NUMBER
};
bool valid = true; bool valid = true;
bool parsedFileNumber = false;
int line = 0, file = 0; int line = 0, file = 0;
int state = LINE_NUMBER;
MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics, false); MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics, false);
// Lex the first token after "#line" so we can check it for EOD.
macroExpander.lex(token); macroExpander.lex(token);
while ((token->type != '\n') && (token->type != Token::LAST))
if (isEOD(token))
{ {
switch (state++) mDiagnostics->report(Diagnostics::PP_INVALID_LINE_DIRECTIVE, token->location, token->text);
valid = false;
}
else
{
ExpressionParser expressionParser(&macroExpander, mDiagnostics);
ExpressionParser::ErrorSettings errorSettings;
// See GLES3 section 12.42
errorSettings.integerLiteralsMustFit32BitSignedRange = true;
errorSettings.unexpectedIdentifier = Diagnostics::PP_INVALID_LINE_NUMBER;
// The first token was lexed earlier to check if it was EOD. Include
// the token in parsing for a second time by setting the
// parsePresetToken flag to true.
expressionParser.parse(token, &line, true, errorSettings, &valid);
if (!isEOD(token) && valid)
{
errorSettings.unexpectedIdentifier = Diagnostics::PP_INVALID_FILE_NUMBER;
// After parsing the line expression expressionParser has also
// advanced to the first token of the file expression - this is the
// token that makes the parser reduce the "input" rule for the line
// expression and stop. So we're using parsePresetToken = true here
// as well.
expressionParser.parse(token, &file, true, errorSettings, &valid);
parsedFileNumber = true;
}
if (!isEOD(token))
{ {
case LINE_NUMBER:
if (valid && (token->type != Token::CONST_INT))
{
mDiagnostics->report(Diagnostics::PP_INVALID_LINE_NUMBER,
token->location, token->text);
valid = false;
}
if (valid && !token->iValue(&line))
{
mDiagnostics->report(Diagnostics::PP_INTEGER_OVERFLOW,
token->location, token->text);
valid = false;
}
break;
case FILE_NUMBER:
if (valid && (token->type != Token::CONST_INT))
{
mDiagnostics->report(Diagnostics::PP_INVALID_FILE_NUMBER,
token->location, token->text);
valid = false;
}
if (valid && !token->iValue(&file))
{
mDiagnostics->report(Diagnostics::PP_INTEGER_OVERFLOW,
token->location, token->text);
valid = false;
}
break;
default:
if (valid) if (valid)
{ {
mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
token->location, token->text); token->location, token->text);
valid = false; valid = false;
} }
break; skipUntilEOD(mTokenizer, token);
} }
macroExpander.lex(token);
} }
if (valid && (state != FILE_NUMBER) && (state != FILE_NUMBER + 1))
{
mDiagnostics->report(Diagnostics::PP_INVALID_LINE_DIRECTIVE,
token->location, token->text);
valid = false;
}
if (valid) if (valid)
{ {
mTokenizer->setLineNumber(line); mTokenizer->setLineNumber(line);
if (state == FILE_NUMBER + 1) if (parsedFileNumber)
mTokenizer->setFileNumber(file); mTokenizer->setFileNumber(file);
} }
} }
...@@ -893,7 +881,12 @@ int DirectiveParser::parseExpressionIf(Token *token) ...@@ -893,7 +881,12 @@ int DirectiveParser::parseExpressionIf(Token *token)
ExpressionParser expressionParser(&macroExpander, mDiagnostics); ExpressionParser expressionParser(&macroExpander, mDiagnostics);
int expression = 0; int expression = 0;
expressionParser.parse(token, &expression); ExpressionParser::ErrorSettings errorSettings;
errorSettings.integerLiteralsMustFit32BitSignedRange = false;
errorSettings.unexpectedIdentifier = Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN;
bool valid = true;
expressionParser.parse(token, &expression, false, errorSettings, &valid);
// Check if there are tokens after #if expression. // Check if there are tokens after #if expression.
if (!isEOD(token)) if (!isEOD(token))
......
...@@ -123,6 +123,10 @@ struct Context ...@@ -123,6 +123,10 @@ struct Context
pp::Lexer* lexer; pp::Lexer* lexer;
pp::Token* token; pp::Token* token;
int* result; int* result;
bool parsePresetToken;
pp::ExpressionParser::ErrorSettings errorSettings;
bool *valid;
void startIgnoreErrors() { ++ignoreErrors; } void startIgnoreErrors() { ++ignoreErrors; }
void endIgnoreErrors() { --ignoreErrors; } void endIgnoreErrors() { --ignoreErrors; }
...@@ -496,9 +500,9 @@ static const yytype_uint8 yytranslate[] = ...@@ -496,9 +500,9 @@ static const yytype_uint8 yytranslate[] =
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] = static const yytype_uint16 yyrline[] =
{ {
0, 106, 106, 113, 114, 124, 124, 145, 145, 166, 0, 110, 110, 117, 118, 129, 129, 150, 150, 171,
169, 172, 175, 178, 181, 184, 187, 190, 193, 196, 174, 177, 180, 183, 186, 189, 192, 195, 198, 201,
199, 202, 205, 224, 243, 246, 249, 252, 255, 258 204, 207, 210, 230, 250, 253, 256, 259, 262, 265
}; };
#endif #endif
...@@ -1343,8 +1347,9 @@ yyreduce: ...@@ -1343,8 +1347,9 @@ yyreduce:
{ {
// This rule should be applied right after the token is lexed, so we can // This rule should be applied right after the token is lexed, so we can
// refer to context->token in the error message. // refer to context->token in the error message.
context->diagnostics->report(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, context->diagnostics->report(context->errorSettings.unexpectedIdentifier,
context->token->location, context->token->text); context->token->location, context->token->text);
*(context->valid) = false;
} }
(yyval) = (yyvsp[0]); (yyval) = (yyvsp[0]);
} }
...@@ -1532,6 +1537,7 @@ yyreduce: ...@@ -1532,6 +1537,7 @@ yyreduce:
context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO, context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
context->token->location, context->token->location,
text.c_str()); text.c_str());
*(context->valid) = false;
} }
(yyval) = static_cast<YYSTYPE>(0); (yyval) = static_cast<YYSTYPE>(0);
} }
...@@ -1556,6 +1562,7 @@ yyreduce: ...@@ -1556,6 +1562,7 @@ yyreduce:
context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO, context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
context->token->location, context->token->location,
text.c_str()); text.c_str());
*(context->valid) = false;
} }
(yyval) = static_cast<YYSTYPE>(0); (yyval) = static_cast<YYSTYPE>(0);
} }
...@@ -1850,7 +1857,11 @@ yyreturn: ...@@ -1850,7 +1857,11 @@ yyreturn:
int yylex(YYSTYPE *lvalp, Context *context) int yylex(YYSTYPE *lvalp, Context *context)
{ {
pp::Token *token = context->token; pp::Token *token = context->token;
context->lexer->lex(token); if (!context->parsePresetToken)
{
context->lexer->lex(token);
}
context->parsePresetToken = false;
int type = 0; int type = 0;
...@@ -1858,10 +1869,13 @@ int yylex(YYSTYPE *lvalp, Context *context) ...@@ -1858,10 +1869,13 @@ int yylex(YYSTYPE *lvalp, Context *context)
{ {
case pp::Token::CONST_INT: { case pp::Token::CONST_INT: {
unsigned int val = 0; unsigned int val = 0;
if (!token->uValue(&val)) int testVal = 0;
if (!token->uValue(&val) || (!token->iValue(&testVal) &&
context->errorSettings.integerLiteralsMustFit32BitSignedRange))
{ {
context->diagnostics->report(pp::Diagnostics::PP_INTEGER_OVERFLOW, context->diagnostics->report(pp::Diagnostics::PP_INTEGER_OVERFLOW,
token->location, token->text); token->location, token->text);
*(context->valid) = false;
} }
*lvalp = static_cast<YYSTYPE>(val); *lvalp = static_cast<YYSTYPE>(val);
type = TOK_CONST_INT; type = TOK_CONST_INT;
...@@ -1934,7 +1948,11 @@ ExpressionParser::ExpressionParser(Lexer *lexer, Diagnostics *diagnostics) ...@@ -1934,7 +1948,11 @@ ExpressionParser::ExpressionParser(Lexer *lexer, Diagnostics *diagnostics)
{ {
} }
bool ExpressionParser::parse(Token *token, int *result) bool ExpressionParser::parse(Token *token,
int *result,
bool parsePresetToken,
const ErrorSettings &errorSettings,
bool *valid)
{ {
Context context; Context context;
context.diagnostics = mDiagnostics; context.diagnostics = mDiagnostics;
...@@ -1942,6 +1960,9 @@ bool ExpressionParser::parse(Token *token, int *result) ...@@ -1942,6 +1960,9 @@ bool ExpressionParser::parse(Token *token, int *result)
context.token = token; context.token = token;
context.result = result; context.result = result;
context.ignoreErrors = 0; context.ignoreErrors = 0;
context.parsePresetToken = parsePresetToken;
context.errorSettings = errorSettings;
context.valid = valid;
int ret = yyparse(&context); int ret = yyparse(&context);
switch (ret) switch (ret)
{ {
......
...@@ -7,21 +7,31 @@ ...@@ -7,21 +7,31 @@
#ifndef COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_ #ifndef COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_
#define COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_ #define COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_
#include "DiagnosticsBase.h"
#include "pp_utils.h" #include "pp_utils.h"
namespace pp namespace pp
{ {
class Diagnostics;
class Lexer; class Lexer;
struct Token; struct Token;
class ExpressionParser class ExpressionParser
{ {
public: public:
struct ErrorSettings
{
Diagnostics::ID unexpectedIdentifier;
bool integerLiteralsMustFit32BitSignedRange;
};
ExpressionParser(Lexer *lexer, Diagnostics *diagnostics); ExpressionParser(Lexer *lexer, Diagnostics *diagnostics);
bool parse(Token *token, int *result); bool parse(Token *token,
int *result,
bool parsePresetToken,
const ErrorSettings &errorSettings,
bool *valid);
private: private:
PP_DISALLOW_COPY_AND_ASSIGN(ExpressionParser); PP_DISALLOW_COPY_AND_ASSIGN(ExpressionParser);
......
...@@ -65,6 +65,10 @@ struct Context ...@@ -65,6 +65,10 @@ struct Context
pp::Lexer* lexer; pp::Lexer* lexer;
pp::Token* token; pp::Token* token;
int* result; int* result;
bool parsePresetToken;
pp::ExpressionParser::ErrorSettings errorSettings;
bool *valid;
void startIgnoreErrors() { ++ignoreErrors; } void startIgnoreErrors() { ++ignoreErrors; }
void endIgnoreErrors() { --ignoreErrors; } void endIgnoreErrors() { --ignoreErrors; }
...@@ -116,8 +120,9 @@ expression ...@@ -116,8 +120,9 @@ expression
{ {
// This rule should be applied right after the token is lexed, so we can // This rule should be applied right after the token is lexed, so we can
// refer to context->token in the error message. // refer to context->token in the error message.
context->diagnostics->report(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, context->diagnostics->report(context->errorSettings.unexpectedIdentifier,
context->token->location, context->token->text); context->token->location, context->token->text);
*(context->valid) = false;
} }
$$ = $1; $$ = $1;
} }
...@@ -213,6 +218,7 @@ expression ...@@ -213,6 +218,7 @@ expression
context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO, context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
context->token->location, context->token->location,
text.c_str()); text.c_str());
*(context->valid) = false;
} }
$$ = static_cast<YYSTYPE>(0); $$ = static_cast<YYSTYPE>(0);
} }
...@@ -232,6 +238,7 @@ expression ...@@ -232,6 +238,7 @@ expression
context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO, context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
context->token->location, context->token->location,
text.c_str()); text.c_str());
*(context->valid) = false;
} }
$$ = static_cast<YYSTYPE>(0); $$ = static_cast<YYSTYPE>(0);
} }
...@@ -265,7 +272,11 @@ expression ...@@ -265,7 +272,11 @@ expression
int yylex(YYSTYPE *lvalp, Context *context) int yylex(YYSTYPE *lvalp, Context *context)
{ {
pp::Token *token = context->token; pp::Token *token = context->token;
context->lexer->lex(token); if (!context->parsePresetToken)
{
context->lexer->lex(token);
}
context->parsePresetToken = false;
int type = 0; int type = 0;
...@@ -273,10 +284,13 @@ int yylex(YYSTYPE *lvalp, Context *context) ...@@ -273,10 +284,13 @@ int yylex(YYSTYPE *lvalp, Context *context)
{ {
case pp::Token::CONST_INT: { case pp::Token::CONST_INT: {
unsigned int val = 0; unsigned int val = 0;
if (!token->uValue(&val)) int testVal = 0;
if (!token->uValue(&val) || (!token->iValue(&testVal) &&
context->errorSettings.integerLiteralsMustFit32BitSignedRange))
{ {
context->diagnostics->report(pp::Diagnostics::PP_INTEGER_OVERFLOW, context->diagnostics->report(pp::Diagnostics::PP_INTEGER_OVERFLOW,
token->location, token->text); token->location, token->text);
*(context->valid) = false;
} }
*lvalp = static_cast<YYSTYPE>(val); *lvalp = static_cast<YYSTYPE>(val);
type = TOK_CONST_INT; type = TOK_CONST_INT;
...@@ -349,7 +363,11 @@ ExpressionParser::ExpressionParser(Lexer *lexer, Diagnostics *diagnostics) ...@@ -349,7 +363,11 @@ ExpressionParser::ExpressionParser(Lexer *lexer, Diagnostics *diagnostics)
{ {
} }
bool ExpressionParser::parse(Token *token, int *result) bool ExpressionParser::parse(Token *token,
int *result,
bool parsePresetToken,
const ErrorSettings &errorSettings,
bool *valid)
{ {
Context context; Context context;
context.diagnostics = mDiagnostics; context.diagnostics = mDiagnostics;
...@@ -357,6 +375,9 @@ bool ExpressionParser::parse(Token *token, int *result) ...@@ -357,6 +375,9 @@ bool ExpressionParser::parse(Token *token, int *result)
context.token = token; context.token = token;
context.result = result; context.result = result;
context.ignoreErrors = 0; context.ignoreErrors = 0;
context.parsePresetToken = parsePresetToken;
context.errorSettings = errorSettings;
context.valid = valid;
int ret = yyparse(&context); int ret = yyparse(&context);
switch (ret) switch (ret)
{ {
......
...@@ -205,15 +205,6 @@ ...@@ -205,15 +205,6 @@
989 WIN LINUX : dEQP-GLES2.functional.shaders.preprocessor.basic.identifier_with_double_underscore_vertex = FAIL 989 WIN LINUX : dEQP-GLES2.functional.shaders.preprocessor.basic.identifier_with_double_underscore_vertex = FAIL
989 WIN LINUX : dEQP-GLES2.functional.shaders.preprocessor.basic.identifier_with_double_underscore_fragment = FAIL 989 WIN LINUX : dEQP-GLES2.functional.shaders.preprocessor.basic.identifier_with_double_underscore_fragment = FAIL
989 WIN LINUX : dEQP-GLES2.functional.shaders.preprocessor.predefined_macros.line_2_vertex = FAIL
989 WIN LINUX : dEQP-GLES2.functional.shaders.preprocessor.predefined_macros.line_2_fragment = FAIL
989 WIN LINUX : dEQP-GLES2.functional.shaders.preprocessor.conditional_inclusion.basic_2_vertex = FAIL
989 WIN LINUX : dEQP-GLES2.functional.shaders.preprocessor.conditional_inclusion.basic_2_fragment = FAIL
989 WIN LINUX : dEQP-GLES2.functional.shaders.preprocessor.undefined_identifiers.valid_undefined_identifier_* = FAIL
989 WIN LINUX : dEQP-GLES2.functional.shaders.preprocessor.builtin.line_expression_vertex = FAIL
989 WIN LINUX : dEQP-GLES2.functional.shaders.preprocessor.builtin.line_expression_fragment = FAIL
989 WIN LINUX : dEQP-GLES2.functional.shaders.preprocessor.builtin.line_and_file_expression_vertex = FAIL
989 WIN LINUX : dEQP-GLES2.functional.shaders.preprocessor.builtin.line_and_file_expression_fragment = FAIL
989 WIN LINUX : dEQP-GLES2.functional.shaders.preprocessor.extensions.after_non_preprocessing_tokens_vertex = FAIL 989 WIN LINUX : dEQP-GLES2.functional.shaders.preprocessor.extensions.after_non_preprocessing_tokens_vertex = FAIL
989 WIN LINUX : dEQP-GLES2.functional.shaders.preprocessor.extensions.after_non_preprocessing_tokens_fragment = FAIL 989 WIN LINUX : dEQP-GLES2.functional.shaders.preprocessor.extensions.after_non_preprocessing_tokens_fragment = FAIL
1015 WIN LINUX : dEQP-GLES2.functional.shaders.functions.invalid.return_array_in_struct_vertex = FAIL 1015 WIN LINUX : dEQP-GLES2.functional.shaders.functions.invalid.return_array_in_struct_vertex = FAIL
......
...@@ -45,34 +45,6 @@ ...@@ -45,34 +45,6 @@
1087 WIN : dEQP-GLES3.functional.implementation_limits.max_fragment_uniform_components = FAIL 1087 WIN : dEQP-GLES3.functional.implementation_limits.max_fragment_uniform_components = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.basic.identifier_with_double_underscore_vertex = FAIL 989 WIN : dEQP-GLES3.functional.shaders.preprocessor.basic.identifier_with_double_underscore_vertex = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.basic.identifier_with_double_underscore_fragment = FAIL 989 WIN : dEQP-GLES3.functional.shaders.preprocessor.basic.identifier_with_double_underscore_fragment = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.line_continuation.comment_vertex = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.line_continuation.comment_fragment = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.line_continuation.preprocessing_token_vertex = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.line_continuation.preprocessing_token_fragment = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.line_continuation.token_vertex = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.line_continuation.token_fragment = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.predefined_macros.version_vertex = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.predefined_macros.version_fragment = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.predefined_macros.line_2_vertex = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.predefined_macros.line_2_fragment = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.predefined_macros.if_version_vertex = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.predefined_macros.if_version_fragment = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.conditional_inclusion.basic_2_vertex = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.conditional_inclusion.basic_2_fragment = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.undefined_identifiers.valid_undefined_identifier_1_vertex = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.undefined_identifiers.valid_undefined_identifier_1_fragment = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.undefined_identifiers.valid_undefined_identifier_2_vertex = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.undefined_identifiers.valid_undefined_identifier_2_fragment = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.conditionals.nested_if_1_vertex = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.conditionals.nested_if_1_fragment = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.builtin.line_expression_vertex = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.builtin.line_expression_fragment = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.builtin.line_and_file_expression_vertex = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.builtin.line_and_file_expression_fragment = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.pragmas.pragma_unrecognized_debug_vertex = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.pragmas.pragma_unrecognized_debug_fragment = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.pragmas.pragma_unrecognized_token_vertex = FAIL
989 WIN : dEQP-GLES3.functional.shaders.preprocessor.pragmas.pragma_unrecognized_token_fragment = FAIL
1088 WIN : dEQP-GLES3.functional.shaders.linkage.varying.rules.invalid_type_struct_array = FAIL 1088 WIN : dEQP-GLES3.functional.shaders.linkage.varying.rules.invalid_type_struct_array = FAIL
1088 WIN : dEQP-GLES3.functional.shaders.linkage.varying.rules.invalid_type_struct_struct = FAIL 1088 WIN : dEQP-GLES3.functional.shaders.linkage.varying.rules.invalid_type_struct_struct = FAIL
1088 WIN : dEQP-GLES3.functional.shaders.linkage.varying.rules.invalid_type_array_struct = FAIL 1088 WIN : dEQP-GLES3.functional.shaders.linkage.varying.rules.invalid_type_array_struct = FAIL
......
...@@ -294,10 +294,58 @@ TEST_P(InvalidLineTest, Identified) ...@@ -294,10 +294,58 @@ TEST_P(InvalidLineTest, Identified)
static const LineTestParam kParams[] = { static const LineTestParam kParams[] = {
{"#line\n", pp::Diagnostics::PP_INVALID_LINE_DIRECTIVE}, {"#line\n", pp::Diagnostics::PP_INVALID_LINE_DIRECTIVE},
{"#line foo\n", pp::Diagnostics::PP_INVALID_LINE_NUMBER}, {"#line foo\n", pp::Diagnostics::PP_INVALID_LINE_NUMBER},
{"#line defined(foo)\n", pp::Diagnostics::PP_INVALID_LINE_NUMBER},
{"#line 10 foo\n", pp::Diagnostics::PP_INVALID_FILE_NUMBER}, {"#line 10 foo\n", pp::Diagnostics::PP_INVALID_FILE_NUMBER},
{"#line 10 20 foo\n", pp::Diagnostics::PP_UNEXPECTED_TOKEN}, {"#line 10 20 foo\n", pp::Diagnostics::PP_UNEXPECTED_TOKEN},
{"#line 0xffffffff\n", pp::Diagnostics::PP_INTEGER_OVERFLOW}, {"#line 0xffffffff\n", pp::Diagnostics::PP_INTEGER_OVERFLOW},
{"#line 10 0xffffffff\n", pp::Diagnostics::PP_INTEGER_OVERFLOW} {"#line 10 0xffffffff\n", pp::Diagnostics::PP_INTEGER_OVERFLOW}};
};
INSTANTIATE_TEST_CASE_P(All, InvalidLineTest, testing::ValuesIn(kParams)); INSTANTIATE_TEST_CASE_P(All, InvalidLineTest, testing::ValuesIn(kParams));
struct LineExpressionTestParam
{
const char *expression;
int expectedLine;
};
class LineExpressionTest : public LocationTest,
public testing::WithParamInterface<LineExpressionTestParam>
{
};
TEST_P(LineExpressionTest, ExpressionEvaluation)
{
LineExpressionTestParam param = GetParam();
const char *strs[3] = {"#line ", param.expression, "\nfoo"};
pp::SourceLocation loc(2, param.expectedLine);
expectLocation(3, strs, NULL, loc);
}
static const LineExpressionTestParam kParamsLineExpressionTest[] = {
{"1 + 2", 3},
{"5 - 3", 2},
{"7 * 11", 77},
{"20 / 10", 2},
{"10 % 5", 0},
{"7 && 3", 1},
{"7 || 0", 1},
{"11 == 11", 1},
{"11 != 11", 0},
{"11 > 7", 1},
{"11 < 7", 0},
{"11 >= 7", 1},
{"11 <= 7", 0},
{"!11", 0},
{"-1", -1},
{"+9", 9},
{"(1 + 2) * 4", 12},
{"3 | 5", 7},
{"3 ^ 5", 6},
{"3 & 5", 1},
{"~5", ~5},
{"2 << 3", 16},
{"16 >> 2", 4}};
INSTANTIATE_TEST_CASE_P(All, LineExpressionTest, testing::ValuesIn(kParamsLineExpressionTest));
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