aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libs/3rdparty/cplusplus/Parser.cpp9
-rw-r--r--src/libs/3rdparty/cplusplus/Parser.h3
-rw-r--r--src/libs/3rdparty/cplusplus/TranslationUnit.cpp5
-rw-r--r--src/libs/3rdparty/cplusplus/TranslationUnit.h5
-rw-r--r--src/libs/cplusplus/CppDocument.cpp7
-rw-r--r--src/libs/cplusplus/CppDocument.h1
-rw-r--r--src/plugins/cpptools/cppsemanticinfoupdater.cpp1
-rw-r--r--tests/auto/cplusplus/ast/tst_ast.cpp27
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);