diff options
-rw-r--r-- | src/libs/3rdparty/cplusplus/Parser.cpp | 9 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/Parser.h | 3 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/TranslationUnit.cpp | 5 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/TranslationUnit.h | 5 | ||||
-rw-r--r-- | src/libs/cplusplus/CppDocument.cpp | 7 | ||||
-rw-r--r-- | src/libs/cplusplus/CppDocument.h | 1 | ||||
-rw-r--r-- | src/plugins/cpptools/cppsemanticinfoupdater.cpp | 1 | ||||
-rw-r--r-- | tests/auto/cplusplus/ast/tst_ast.cpp | 27 |
8 files changed, 49 insertions, 9 deletions
diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp index 11656bd47f1..c98f92cc37b 100644 --- a/src/libs/3rdparty/cplusplus/Parser.cpp +++ b/src/libs/3rdparty/cplusplus/Parser.cpp @@ -66,8 +66,6 @@ public: int DebugRule::depth = 0; -const int declarationsInRowAllowedToFail = 2; - inline bool lookAtAssignmentOperator(int tokenKind) { switch (tokenKind) { @@ -267,12 +265,13 @@ inline void debugPrintCheckCache(bool) {} return true; \ } -Parser::Parser(TranslationUnit *unit) +Parser::Parser(TranslationUnit *unit, int retryParseDeclarationLimit) : _translationUnit(unit), _control(unit->control()), _pool(unit->memoryPool()), _languageFeatures(unit->languageFeatures()), _tokenIndex(1), + _retryParseDeclarationLimit(retryParseDeclarationLimit), _templateArguments(0), _inFunctionBody(false), _inExpressionStatement(false), @@ -657,7 +656,7 @@ bool Parser::parseTranslationUnit(TranslationUnitAST *&node) } else { error(start_declaration, "expected a declaration"); rewind(start_declaration + 1); - if (++declarationsInRowFailedToParse == declarationsInRowAllowedToFail) + if (++declarationsInRowFailedToParse == _retryParseDeclarationLimit) skipUntilAfterSemicolonOrRightBrace(); else skipUntilDeclaration(); @@ -825,7 +824,7 @@ bool Parser::parseLinkageBody(DeclarationAST *&node) } else { error(start_declaration, "expected a declaration"); rewind(start_declaration + 1); - if (++declarationsInRowFailedToParse == declarationsInRowAllowedToFail) + if (++declarationsInRowFailedToParse == _retryParseDeclarationLimit) skipUntilAfterSemicolonOrRightBrace(); else skipUntilDeclaration(); diff --git a/src/libs/3rdparty/cplusplus/Parser.h b/src/libs/3rdparty/cplusplus/Parser.h index 923b0c4dc82..5f0a182bd12 100644 --- a/src/libs/3rdparty/cplusplus/Parser.h +++ b/src/libs/3rdparty/cplusplus/Parser.h @@ -33,7 +33,7 @@ namespace CPlusPlus { class CPLUSPLUS_EXPORT Parser { public: - Parser(TranslationUnit *translationUnit); + Parser(TranslationUnit *translationUnit, int retryParseDeclarationLimit); ~Parser(); bool parseTranslationUnit(TranslationUnitAST *&node); @@ -317,6 +317,7 @@ private: MemoryPool *_pool; LanguageFeatures _languageFeatures; unsigned _tokenIndex; + int _retryParseDeclarationLimit; bool _templateArguments: 1; bool _inFunctionBody: 1; bool _inExpressionStatement: 1; diff --git a/src/libs/3rdparty/cplusplus/TranslationUnit.cpp b/src/libs/3rdparty/cplusplus/TranslationUnit.cpp index ace6eda549a..86eb25f1e35 100644 --- a/src/libs/3rdparty/cplusplus/TranslationUnit.cpp +++ b/src/libs/3rdparty/cplusplus/TranslationUnit.cpp @@ -49,7 +49,8 @@ TranslationUnit::TranslationUnit(Control *control, const StringLiteral *fileId) _lastSourceChar(0), _pool(0), _ast(0), - _flags(0) + _flags(0), + _retryParseDeclarationLimit(defaultRetryParseDeclarationLimit()) { _tokens = new std::vector<Token>(); _comments = new std::vector<Token>(); @@ -299,7 +300,7 @@ bool TranslationUnit::parse(ParseMode mode) f._parsed = true; - Parser parser(this); + Parser parser(this, _retryParseDeclarationLimit); bool parsed = false; switch (mode) { diff --git a/src/libs/3rdparty/cplusplus/TranslationUnit.h b/src/libs/3rdparty/cplusplus/TranslationUnit.h index 94eb81666be..eb4e1f2e3a5 100644 --- a/src/libs/3rdparty/cplusplus/TranslationUnit.h +++ b/src/libs/3rdparty/cplusplus/TranslationUnit.h @@ -149,6 +149,9 @@ public: LanguageFeatures languageFeatures() const { return _languageFeatures; } void setLanguageFeatures(LanguageFeatures features) { _languageFeatures = features; } + static int defaultRetryParseDeclarationLimit() { return 2; } + void setRetryParseDeclarationLimit(int limit) { _retryParseDeclarationLimit = limit; } + private: struct PPLine { unsigned utf16charOffset; @@ -210,6 +213,8 @@ private: Flags f; }; LanguageFeatures _languageFeatures; + + int _retryParseDeclarationLimit; }; } // namespace CPlusPlus diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp index 6c51ff5f3b0..3eea3c80c16 100644 --- a/src/libs/cplusplus/CppDocument.cpp +++ b/src/libs/cplusplus/CppDocument.cpp @@ -623,6 +623,13 @@ void Document::tokenize() _translationUnit->tokenize(); } +void Document::setRetryHarderToParseDeclarations(bool yesno) +{ + _translationUnit->setRetryParseDeclarationLimit( + yesno ? 1000 + : TranslationUnit::defaultRetryParseDeclarationLimit()); +} + bool Document::isParsed() const { return _translationUnit->isParsed(); diff --git a/src/libs/cplusplus/CppDocument.h b/src/libs/cplusplus/CppDocument.h index c680a0751e9..f840737d474 100644 --- a/src/libs/cplusplus/CppDocument.h +++ b/src/libs/cplusplus/CppDocument.h @@ -127,6 +127,7 @@ public: bool isTokenized() const; void tokenize(); + void setRetryHarderToParseDeclarations(bool yesno); bool isParsed() const; bool parse(ParseMode mode = ParseTranlationUnit); diff --git a/src/plugins/cpptools/cppsemanticinfoupdater.cpp b/src/plugins/cpptools/cppsemanticinfoupdater.cpp index 2ee0501aa72..9c9d87ac6a2 100644 --- a/src/plugins/cpptools/cppsemanticinfoupdater.cpp +++ b/src/plugins/cpptools/cppsemanticinfoupdater.cpp @@ -125,6 +125,7 @@ SemanticInfo SemanticInfoUpdaterPrivate::update(const SemanticInfo::Source &sour Document::Ptr doc = newSemanticInfo.snapshot.preprocessedDocument(source.code, source.fileName); if (processor) doc->control()->setTopLevelDeclarationProcessor(processor); + doc->setRetryHarderToParseDeclarations(true); doc->check(); if (processor && processor->isCanceled()) newSemanticInfo.complete = false; diff --git a/tests/auto/cplusplus/ast/tst_ast.cpp b/tests/auto/cplusplus/ast/tst_ast.cpp index 1691919012f..30e56b2350c 100644 --- a/tests/auto/cplusplus/ast/tst_ast.cpp +++ b/tests/auto/cplusplus/ast/tst_ast.cpp @@ -51,7 +51,9 @@ public: TranslationUnit::ParseMode mode, bool blockErrors = false, bool qtMocRun = false, - bool cxx11Enabled = false) + bool cxx11Enabled = false, + int retryParseDeclarationLimit + = TranslationUnit::defaultRetryParseDeclarationLimit()) { const StringLiteral *fileId = control.stringLiteral("<stdin>"); LanguageFeatures features; @@ -62,6 +64,7 @@ public: features.qtMocRunEnabled = qtMocRun; TranslationUnit *unit = new TranslationUnit(&control, fileId); unit->setLanguageFeatures(features); + unit->setRetryParseDeclarationLimit(retryParseDeclarationLimit); unit->setSource(source.constData(), source.length()); unit->blockErrors(blockErrors); unit->parse(mode); @@ -199,6 +202,7 @@ private slots: void unnamed_class(); void unnamed_class_data(); void expensiveExpression(); + void invalidCode(); }; void tst_AST::gcc_attributes_1() @@ -1856,6 +1860,27 @@ void tst_AST::expensiveExpression() QVERIFY(unit->ast()); } +void tst_AST::invalidCode() +{ + const QByteArray invalidCode = "static inValidLine()\n" + "class Foo {};\n"; + + QSharedPointer<TranslationUnit> unit(parse(invalidCode, TranslationUnit::ParseTranlationUnit, + false, false, false, 1000)); + QVERIFY(unit->ast()); + TranslationUnitAST *unitAST = unit->ast()->asTranslationUnit(); + QVERIFY(unitAST->declaration_list); + QVERIFY(unitAST->declaration_list->value); + SimpleDeclarationAST *simpleDecl = unitAST->declaration_list->value->asSimpleDeclaration(); + QVERIFY(simpleDecl); + QVERIFY(simpleDecl->decl_specifier_list); + QVERIFY(simpleDecl->decl_specifier_list->value); + ClassSpecifierAST *classSpecifier = simpleDecl->decl_specifier_list->value->asClassSpecifier(); + QVERIFY(classSpecifier); + + QVERIFY(diag.errorCount != 0); +} + void tst_AST::initTestCase() { control.setDiagnosticClient(&diag); |