aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/3rdparty/cplusplus/Parser.cpp
diff options
context:
space:
mode:
authorNikolai Kosjar <nikolai.kosjar@theqtcompany.com>2014-11-18 11:58:37 +0100
committerNikolai Kosjar <nikolai.kosjar@theqtcompany.com>2014-11-18 13:46:34 +0100
commit78ab287fc6d3770646012e461b0a518db4e9c9f4 (patch)
tree530e3492ed4b7aaff18cf20ac25010872639fa0d /src/libs/3rdparty/cplusplus/Parser.cpp
parent657797f7a06de9c5297952896421fc94a360b848 (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.cpp32
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();