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 | |
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')
-rw-r--r-- | src/libs/3rdparty/cplusplus/Parser.cpp | 32 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/Parser.h | 1 |
2 files changed, 31 insertions, 2 deletions
diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp index 86eeaa2f2a4..11656bd47f1 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(); diff --git a/src/libs/3rdparty/cplusplus/Parser.h b/src/libs/3rdparty/cplusplus/Parser.h index 4a2a6dfb7e0..923b0c4dc82 100644 --- a/src/libs/3rdparty/cplusplus/Parser.h +++ b/src/libs/3rdparty/cplusplus/Parser.h @@ -254,6 +254,7 @@ public: bool parseDesignator(DesignatorAST *&node); bool skipUntil(int token); + void skipUntilAfterSemicolonOrRightBrace(); void skipUntilDeclaration(); bool skipUntilStatement(); bool skip(int l, int r); |