diff options
author | Nikolai Kosjar <nikolai.kosjar@theqtcompany.com> | 2014-11-18 11:58:37 +0100 |
---|---|---|
committer | Nikolai Kosjar <nikolai.kosjar@theqtcompany.com> | 2014-11-18 13:46:34 +0100 |
commit | 78ab287fc6d3770646012e461b0a518db4e9c9f4 (patch) | |
tree | 530e3492ed4b7aaff18cf20ac25010872639fa0d /src/libs/3rdparty/cplusplus/Parser.cpp | |
parent | 657797f7a06de9c5297952896421fc94a360b848 (diff) |
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: Erik Verbruggen <erik.verbruggen@theqtcompany.com>
Diffstat (limited to 'src/libs/3rdparty/cplusplus/Parser.cpp')
-rw-r--r-- | src/libs/3rdparty/cplusplus/Parser.cpp | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp index 86eeaa2f2a..11656bd47f 100644 --- a/src/libs/3rdparty/cplusplus/Parser.cpp +++ b/src/libs/3rdparty/cplusplus/Parser.cpp @@ -66,6 +66,8 @@ public: int DebugRule::depth = 0; +const int declarationsInRowAllowedToFail = 2; + inline bool lookAtAssignmentOperator(int tokenKind) { switch (tokenKind) { @@ -310,6 +312,20 @@ bool Parser::skipUntil(int token) return false; } +void Parser::skipUntilAfterSemicolonOrRightBrace() +{ + while (int tk = LA()) { + switch (tk) { + case T_SEMICOLON: + case T_RBRACE: + consumeToken(); + return; + default: + consumeToken(); + } + } +} + void Parser::skipUntilDeclaration() { for (; ; consumeToken()) { @@ -626,19 +642,25 @@ bool Parser::parseTranslationUnit(TranslationUnitAST *&node) TranslationUnitAST *ast = new (_pool) TranslationUnitAST; DeclarationListAST **decl = &ast->declaration_list; + int declarationsInRowFailedToParse = 0; + while (LA()) { unsigned start_declaration = cursor(); DeclarationAST *declaration = 0; if (parseDeclaration(declaration)) { + declarationsInRowFailedToParse = 0; *decl = new (_pool) DeclarationListAST; (*decl)->value = declaration; decl = &(*decl)->next; } else { error(start_declaration, "expected a declaration"); rewind(start_declaration + 1); - skipUntilDeclaration(); + if (++declarationsInRowFailedToParse == declarationsInRowAllowedToFail) + skipUntilAfterSemicolonOrRightBrace(); + else + skipUntilDeclaration(); } @@ -787,6 +809,8 @@ bool Parser::parseLinkageBody(DeclarationAST *&node) ast->lbrace_token = consumeToken(); DeclarationListAST **declaration_ptr = &ast->declaration_list; + int declarationsInRowFailedToParse = 0; + while (int tk = LA()) { if (tk == T_RBRACE) break; @@ -794,13 +818,17 @@ bool Parser::parseLinkageBody(DeclarationAST *&node) unsigned start_declaration = cursor(); DeclarationAST *declaration = 0; if (parseDeclaration(declaration)) { + declarationsInRowFailedToParse = 0; *declaration_ptr = new (_pool) DeclarationListAST; (*declaration_ptr)->value = declaration; declaration_ptr = &(*declaration_ptr)->next; } else { error(start_declaration, "expected a declaration"); rewind(start_declaration + 1); - skipUntilDeclaration(); + if (++declarationsInRowFailedToParse == declarationsInRowAllowedToFail) + skipUntilAfterSemicolonOrRightBrace(); + else + skipUntilDeclaration(); } _templateArgumentList.clear(); |