forked from qt-creator/qt-creator
GLSL: Avoid infinite loop at error recovery
For error recovery additional tokens are tried to produce a valid grammar rule. For the specific case in the bug report for(int x=0; x y the two consecutive identifiers in the end triggered an infinite loop since the identifier token is also part of those additional tokens that are tried. Circumvent this by trying a more conservative list of tokens on the second try. Done-by: Erik Verbruggen Change-Id: I271dddecf947a06ed3af5f9955ee630441533342 Task-number: QTCREATORBUG-18967 Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io> Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
This commit is contained in:
@@ -519,9 +519,13 @@ AST *Parser::parse(int startToken)
|
||||
_recovered = false;
|
||||
_tos = -1;
|
||||
_startToken.kind = startToken;
|
||||
int recoveryAttempts = 0;
|
||||
|
||||
|
||||
do {
|
||||
again:
|
||||
recoveryAttempts = 0;
|
||||
|
||||
againAfterRecovery:
|
||||
if (unsigned(++_tos) == _stateStack.size()) {
|
||||
_stateStack.resize(_tos * 2);
|
||||
_locationStack.resize(_tos * 2);
|
||||
@@ -564,6 +568,7 @@ AST *Parser::parse(int startToken)
|
||||
reduce(ruleno);
|
||||
action = nt_action(_stateStack[_tos], lhs[ruleno] - TERMINAL_COUNT);
|
||||
} else if (action == 0) {
|
||||
++recoveryAttempts;
|
||||
const int line = _tokens[yyloc].line + 1;
|
||||
QString message = QLatin1String("Syntax error");
|
||||
if (yytoken != -1) {
|
||||
@@ -574,7 +579,7 @@ AST *Parser::parse(int startToken)
|
||||
for (; _tos; --_tos) {
|
||||
const int state = _stateStack[_tos];
|
||||
|
||||
static int tks[] = {
|
||||
static int tks1[] = {
|
||||
T_RIGHT_BRACE, T_RIGHT_PAREN, T_RIGHT_BRACKET,
|
||||
T_SEMICOLON, T_COLON, T_COMMA,
|
||||
T_NUMBER, T_TYPE_NAME, T_IDENTIFIER,
|
||||
@@ -582,6 +587,16 @@ AST *Parser::parse(int startToken)
|
||||
T_WHILE,
|
||||
0
|
||||
};
|
||||
static int tks2[] = {
|
||||
T_RIGHT_BRACE, T_RIGHT_PAREN, T_RIGHT_BRACKET,
|
||||
T_SEMICOLON, T_COLON, T_COMMA,
|
||||
0
|
||||
};
|
||||
int *tks;
|
||||
if (recoveryAttempts < 2)
|
||||
tks = tks1;
|
||||
else
|
||||
tks = tks2; // Avoid running into an endless loop for e.g.: for(int x=0; x y
|
||||
|
||||
for (int *tptr = tks; *tptr; ++tptr) {
|
||||
const int next = t_action(state, *tptr);
|
||||
@@ -604,7 +619,7 @@ AST *Parser::parse(int startToken)
|
||||
yytoken = -1;
|
||||
|
||||
action = next;
|
||||
goto again;
|
||||
goto againAfterRecovery;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user