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;
|
_recovered = false;
|
||||||
_tos = -1;
|
_tos = -1;
|
||||||
_startToken.kind = startToken;
|
_startToken.kind = startToken;
|
||||||
|
int recoveryAttempts = 0;
|
||||||
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
again:
|
recoveryAttempts = 0;
|
||||||
|
|
||||||
|
againAfterRecovery:
|
||||||
if (unsigned(++_tos) == _stateStack.size()) {
|
if (unsigned(++_tos) == _stateStack.size()) {
|
||||||
_stateStack.resize(_tos * 2);
|
_stateStack.resize(_tos * 2);
|
||||||
_locationStack.resize(_tos * 2);
|
_locationStack.resize(_tos * 2);
|
||||||
@@ -564,6 +568,7 @@ AST *Parser::parse(int startToken)
|
|||||||
reduce(ruleno);
|
reduce(ruleno);
|
||||||
action = nt_action(_stateStack[_tos], lhs[ruleno] - TERMINAL_COUNT);
|
action = nt_action(_stateStack[_tos], lhs[ruleno] - TERMINAL_COUNT);
|
||||||
} else if (action == 0) {
|
} else if (action == 0) {
|
||||||
|
++recoveryAttempts;
|
||||||
const int line = _tokens[yyloc].line + 1;
|
const int line = _tokens[yyloc].line + 1;
|
||||||
QString message = QLatin1String("Syntax error");
|
QString message = QLatin1String("Syntax error");
|
||||||
if (yytoken != -1) {
|
if (yytoken != -1) {
|
||||||
@@ -574,7 +579,7 @@ AST *Parser::parse(int startToken)
|
|||||||
for (; _tos; --_tos) {
|
for (; _tos; --_tos) {
|
||||||
const int state = _stateStack[_tos];
|
const int state = _stateStack[_tos];
|
||||||
|
|
||||||
static int tks[] = {
|
static int tks1[] = {
|
||||||
T_RIGHT_BRACE, T_RIGHT_PAREN, T_RIGHT_BRACKET,
|
T_RIGHT_BRACE, T_RIGHT_PAREN, T_RIGHT_BRACKET,
|
||||||
T_SEMICOLON, T_COLON, T_COMMA,
|
T_SEMICOLON, T_COLON, T_COMMA,
|
||||||
T_NUMBER, T_TYPE_NAME, T_IDENTIFIER,
|
T_NUMBER, T_TYPE_NAME, T_IDENTIFIER,
|
||||||
@@ -582,6 +587,16 @@ AST *Parser::parse(int startToken)
|
|||||||
T_WHILE,
|
T_WHILE,
|
||||||
0
|
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) {
|
for (int *tptr = tks; *tptr; ++tptr) {
|
||||||
const int next = t_action(state, *tptr);
|
const int next = t_action(state, *tptr);
|
||||||
@@ -604,7 +619,7 @@ AST *Parser::parse(int startToken)
|
|||||||
yytoken = -1;
|
yytoken = -1;
|
||||||
|
|
||||||
action = next;
|
action = next;
|
||||||
goto again;
|
goto againAfterRecovery;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user