From 78ab287fc6d3770646012e461b0a518db4e9c9f4 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Tue, 18 Nov 2014 11:58:37 +0100 Subject: [PATCH] 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 --- src/libs/3rdparty/cplusplus/Parser.cpp | 32 ++++++++++++++++++++++++-- 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);