Commit 78ab287f authored by Nikolai Kosjar's avatar Nikolai Kosjar
Browse files

C++: Stop parsing a declaration after two tries



If we fail to parse a declaration, we rewind, eat the token and look for the
next token that might be a good candidate for a declaration start (e.g. an
identifier). This becomes cpu and memory expensive with super long and invalid
expressions like

    typedef b::m::if_< b::m::bool_<
	(sizeof(fun((Dummy *) 0, (ThisT *) 0, (b::m::int_<70> *) 0)) ==
	 sizeof(defined_)) >, b::m::if_< b::m::bool_<
	(sizeof(fun((Dummy *) 0, (ThisT *) 0, (b::m::int_<71> *) 0)) ==
	 sizeof(defined_)) >, b::m::if_< b::m::bool_<
	(sizeof(fun((Dummy *) 0, (ThisT *) 0, (b::m::int_<72> *) 0)) ==
	 sizeof(defined_)) >, b::m::if_< b::m::bool_<
	(sizeof(fun((Dummy *) 0, (ThisT *) 0, (b::m::int_<73> *) 0)) ==
	 sizeof(defined_)) >, b::m::if_< b::m::bool_<
	(sizeof(fun((Dummy *) 0, (ThisT *) 0, (b::m::int_<74> *) 0)) ==
	 sizeof(defined_)) >, b::m::if_< b::m::bool_<
	(sizeof(fun((Dummy *) 0, (ThisT *) 0, (b::m::int_<75> *) 0)) ==
	 sizeof(defined_)) >, b::m::if_< b::m::bool_<
	// ...some more crazy lines like this

Therefore, stop trying after two failures by looking for the next semicolon or
closing curly brace.

Task-number: QTCREATORBUG-12890
Change-Id: I6637daeb840dd549d669080775228fa91fc932eb
Reviewed-by: default avatarErik Verbruggen <erik.verbruggen@theqtcompany.com>
parent 657797f7
...@@ -66,6 +66,8 @@ public: ...@@ -66,6 +66,8 @@ public:
int DebugRule::depth = 0; int DebugRule::depth = 0;
const int declarationsInRowAllowedToFail = 2;
inline bool lookAtAssignmentOperator(int tokenKind) inline bool lookAtAssignmentOperator(int tokenKind)
{ {
switch (tokenKind) { switch (tokenKind) {
...@@ -310,6 +312,20 @@ bool Parser::skipUntil(int token) ...@@ -310,6 +312,20 @@ bool Parser::skipUntil(int token)
return false; return false;
} }
void Parser::skipUntilAfterSemicolonOrRightBrace()
{
while (int tk = LA()) {
switch (tk) {
case T_SEMICOLON:
case T_RBRACE:
consumeToken();
return;
default:
consumeToken();
}
}
}
void Parser::skipUntilDeclaration() void Parser::skipUntilDeclaration()
{ {
for (; ; consumeToken()) { for (; ; consumeToken()) {
...@@ -626,19 +642,25 @@ bool Parser::parseTranslationUnit(TranslationUnitAST *&node) ...@@ -626,19 +642,25 @@ bool Parser::parseTranslationUnit(TranslationUnitAST *&node)
TranslationUnitAST *ast = new (_pool) TranslationUnitAST; TranslationUnitAST *ast = new (_pool) TranslationUnitAST;
DeclarationListAST **decl = &ast->declaration_list; DeclarationListAST **decl = &ast->declaration_list;
int declarationsInRowFailedToParse = 0;
while (LA()) { while (LA()) {
unsigned start_declaration = cursor(); unsigned start_declaration = cursor();
DeclarationAST *declaration = 0; DeclarationAST *declaration = 0;
if (parseDeclaration(declaration)) { if (parseDeclaration(declaration)) {
declarationsInRowFailedToParse = 0;
*decl = new (_pool) DeclarationListAST; *decl = new (_pool) DeclarationListAST;
(*decl)->value = declaration; (*decl)->value = declaration;
decl = &(*decl)->next; decl = &(*decl)->next;
} else { } else {
error(start_declaration, "expected a declaration"); error(start_declaration, "expected a declaration");
rewind(start_declaration + 1); rewind(start_declaration + 1);
skipUntilDeclaration(); if (++declarationsInRowFailedToParse == declarationsInRowAllowedToFail)
skipUntilAfterSemicolonOrRightBrace();
else
skipUntilDeclaration();
} }
...@@ -787,6 +809,8 @@ bool Parser::parseLinkageBody(DeclarationAST *&node) ...@@ -787,6 +809,8 @@ bool Parser::parseLinkageBody(DeclarationAST *&node)
ast->lbrace_token = consumeToken(); ast->lbrace_token = consumeToken();
DeclarationListAST **declaration_ptr = &ast->declaration_list; DeclarationListAST **declaration_ptr = &ast->declaration_list;
int declarationsInRowFailedToParse = 0;
while (int tk = LA()) { while (int tk = LA()) {
if (tk == T_RBRACE) if (tk == T_RBRACE)
break; break;
...@@ -794,13 +818,17 @@ bool Parser::parseLinkageBody(DeclarationAST *&node) ...@@ -794,13 +818,17 @@ bool Parser::parseLinkageBody(DeclarationAST *&node)
unsigned start_declaration = cursor(); unsigned start_declaration = cursor();
DeclarationAST *declaration = 0; DeclarationAST *declaration = 0;
if (parseDeclaration(declaration)) { if (parseDeclaration(declaration)) {
declarationsInRowFailedToParse = 0;
*declaration_ptr = new (_pool) DeclarationListAST; *declaration_ptr = new (_pool) DeclarationListAST;
(*declaration_ptr)->value = declaration; (*declaration_ptr)->value = declaration;
declaration_ptr = &(*declaration_ptr)->next; declaration_ptr = &(*declaration_ptr)->next;
} else { } else {
error(start_declaration, "expected a declaration"); error(start_declaration, "expected a declaration");
rewind(start_declaration + 1); rewind(start_declaration + 1);
skipUntilDeclaration(); if (++declarationsInRowFailedToParse == declarationsInRowAllowedToFail)
skipUntilAfterSemicolonOrRightBrace();
else
skipUntilDeclaration();
} }
_templateArgumentList.clear(); _templateArgumentList.clear();
......
...@@ -254,6 +254,7 @@ public: ...@@ -254,6 +254,7 @@ public:
bool parseDesignator(DesignatorAST *&node); bool parseDesignator(DesignatorAST *&node);
bool skipUntil(int token); bool skipUntil(int token);
void skipUntilAfterSemicolonOrRightBrace();
void skipUntilDeclaration(); void skipUntilDeclaration();
bool skipUntilStatement(); bool skipUntilStatement();
bool skip(int l, int r); bool skip(int l, int r);
......
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