diff options
author | Nikolai Kosjar <nikolai.kosjar@digia.com> | 2013-06-11 09:22:18 +0200 |
---|---|---|
committer | Nikolai Kosjar <nikolai.kosjar@digia.com> | 2013-06-25 11:04:17 +0200 |
commit | 8aa8f225369603e1e9ea019ca043715b08a61e82 (patch) | |
tree | 494c3fe911e133e17a73d448f3964df725f079fd | |
parent | 1477729aa0590a6f5041164f56d8c7e8e8249d2e (diff) | |
download | qt-creator-8aa8f225369603e1e9ea019ca043715b08a61e82.tar.gz |
C++: Handle recursive auto declarations
Remember auto declarations we have already looked up and stop if we try
it again.
Task-number: QTCREATORBUG-9503
Change-Id: I989b11609c98bf197ce916d79c9d452294355053
Reviewed-by: Przemyslaw Gorszkowski <pgorszkowski@gmail.com>
Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
(cherry picked from commit 8f1b6656677344e9ca4b6798ddd900725c478b16)
-rw-r--r-- | src/libs/cplusplus/ResolveExpression.cpp | 15 | ||||
-rw-r--r-- | src/libs/cplusplus/ResolveExpression.h | 5 | ||||
-rw-r--r-- | src/libs/cplusplus/TypeOfExpression.cpp | 8 | ||||
-rw-r--r-- | src/libs/cplusplus/TypeOfExpression.h | 9 | ||||
-rw-r--r-- | src/plugins/cpptools/cppcompletion_test.cpp | 53 | ||||
-rw-r--r-- | src/plugins/cpptools/cpptoolsplugin.h | 2 |
6 files changed, 82 insertions, 10 deletions
diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index b547c22d68..32dcbeb4e6 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -75,11 +75,13 @@ static QList<_Tp> removeDuplicates(const QList<_Tp> &results) ///////////////////////////////////////////////////////////////////// // ResolveExpression ///////////////////////////////////////////////////////////////////// -ResolveExpression::ResolveExpression(const LookupContext &context) +ResolveExpression::ResolveExpression(const LookupContext &context, + const QSet<const Declaration *> &autoDeclarationsBeingResolved) : ASTVisitor(context.expressionDocument()->translationUnit()), _scope(0), _context(context), bind(context.expressionDocument()->translationUnit()), + _autoDeclarationsBeingResolved(autoDeclarationsBeingResolved), _reference(false) { } @@ -519,6 +521,10 @@ bool ResolveExpression::visit(SimpleNameAST *ast) if (!decl) continue; + // Stop on recursive auto declarations + if (_autoDeclarationsBeingResolved.contains(decl)) + continue; + const StringLiteral *initializationString = decl->getInitializer(); if (initializationString == 0) continue; @@ -533,7 +539,8 @@ bool ResolveExpression::visit(SimpleNameAST *ast) TypeOfExpression exprTyper; Document::Ptr doc = _context.snapshot().document(QString::fromLocal8Bit(decl->fileName())); - exprTyper.init(doc, _context.snapshot(), _context.bindings()); + exprTyper.init(doc, _context.snapshot(), _context.bindings(), + QSet<const Declaration* >(_autoDeclarationsBeingResolved) << decl); Document::Ptr exprDoc = documentForExpression(exprTyper.preprocessedExpression(initializer)); @@ -543,8 +550,8 @@ bool ResolveExpression::visit(SimpleNameAST *ast) if (deduceAuto._block) continue; - const QList<LookupItem> &typeItems = - exprTyper(extractExpressionAST(exprDoc), exprDoc, decl->enclosingScope()); + const QList<LookupItem> &typeItems = exprTyper(extractExpressionAST(exprDoc), exprDoc, + decl->enclosingScope()); if (typeItems.empty()) continue; diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h index e6ce50dde4..922d1b6bf0 100644 --- a/src/libs/cplusplus/ResolveExpression.h +++ b/src/libs/cplusplus/ResolveExpression.h @@ -42,7 +42,9 @@ namespace CPlusPlus { class CPLUSPLUS_EXPORT ResolveExpression: protected ASTVisitor { public: - ResolveExpression(const LookupContext &context); + ResolveExpression(const LookupContext &context, + const QSet<const Declaration *> &autoDeclarationsBeingResolved + = QSet<const Declaration *>()); virtual ~ResolveExpression(); QList<LookupItem> operator()(ExpressionAST *ast, Scope *scope); @@ -125,6 +127,7 @@ private: const LookupContext& _context; Bind bind; QList<LookupItem> _results; + QSet<const Declaration *> _autoDeclarationsBeingResolved; bool _reference; }; diff --git a/src/libs/cplusplus/TypeOfExpression.cpp b/src/libs/cplusplus/TypeOfExpression.cpp index ac813fa873..7025c474c1 100644 --- a/src/libs/cplusplus/TypeOfExpression.cpp +++ b/src/libs/cplusplus/TypeOfExpression.cpp @@ -58,7 +58,8 @@ void TypeOfExpression::reset() } void TypeOfExpression::init(Document::Ptr thisDocument, const Snapshot &snapshot, - QSharedPointer<CreateBindings> bindings) + QSharedPointer<CreateBindings> bindings, + const QSet<const Declaration *> &autoDeclarationsBeingResolved) { m_thisDocument = thisDocument; m_snapshot = snapshot; @@ -67,6 +68,7 @@ void TypeOfExpression::init(Document::Ptr thisDocument, const Snapshot &snapshot m_lookupContext = LookupContext(); m_bindings = bindings; m_environment.clear(); + m_autoDeclarationsBeingResolved = autoDeclarationsBeingResolved; } QList<LookupItem> TypeOfExpression::operator()(const QByteArray &utf8code, @@ -111,7 +113,7 @@ QList<LookupItem> TypeOfExpression::operator()(ExpressionAST *expression, m_lookupContext.setBindings(m_bindings); m_lookupContext.setExpandTemplates(m_expandTemplates); - ResolveExpression resolve(m_lookupContext); + ResolveExpression resolve(m_lookupContext, m_autoDeclarationsBeingResolved); const QList<LookupItem> items = resolve(m_ast, scope); if (! m_bindings) @@ -133,7 +135,7 @@ QList<LookupItem> TypeOfExpression::reference(ExpressionAST *expression, m_lookupContext.setBindings(m_bindings); m_lookupContext.setExpandTemplates(m_expandTemplates); - ResolveExpression resolve(m_lookupContext); + ResolveExpression resolve(m_lookupContext, m_autoDeclarationsBeingResolved); const QList<LookupItem> items = resolve.reference(m_ast, scope); if (! m_bindings) diff --git a/src/libs/cplusplus/TypeOfExpression.h b/src/libs/cplusplus/TypeOfExpression.h index adeb1d9644..a6743e3989 100644 --- a/src/libs/cplusplus/TypeOfExpression.h +++ b/src/libs/cplusplus/TypeOfExpression.h @@ -58,8 +58,11 @@ public: * Also clears the lookup context, so can be used to make sure references * to the documents previously used are removed. */ - void init(Document::Ptr thisDocument, const Snapshot &snapshot, - QSharedPointer<CreateBindings> bindings = QSharedPointer<CreateBindings>()); + void init(Document::Ptr thisDocument, + const Snapshot &snapshot, + QSharedPointer<CreateBindings> bindings = QSharedPointer<CreateBindings>(), + const QSet<const Declaration *> &autoDeclarationsBeingResolved + = QSet<const Declaration *>()); void reset(); @@ -151,6 +154,8 @@ private: // Keep the expression documents and thus all the symbols and // their types alive until they are not needed any more. QList<Document::Ptr> m_documents; + + QSet<const Declaration *> m_autoDeclarationsBeingResolved; }; ExpressionAST CPLUSPLUS_EXPORT *extractExpressionAST(Document::Ptr doc); diff --git a/src/plugins/cpptools/cppcompletion_test.cpp b/src/plugins/cpptools/cppcompletion_test.cpp index 11e380092b..44f9178cdb 100644 --- a/src/plugins/cpptools/cppcompletion_test.cpp +++ b/src/plugins/cpptools/cppcompletion_test.cpp @@ -1832,3 +1832,56 @@ void CppToolsPlugin::test_completion_crash_cloning_template_class_QTCREATORBUG93 QVERIFY(completions.contains(QLatin1String("Templ"))); QVERIFY(completions.contains(QLatin1String("f"))); } + +void CppToolsPlugin::test_completion_recursive_auto_declarations1_QTCREATORBUG9503() +{ + TestData data; + data.srcText = + "void f()\n" + "{\n" + " auto object2 = object1;\n" + " auto object1 = object2;\n" + " @;\n" + " // padding so we get the scope right\n" + "}\n" + ; + setup(&data); + + Utils::ChangeSet change; + QString txt = QLatin1String("object1."); + change.insert(data.pos, txt); + QTextCursor cursor(data.doc); + change.apply(&cursor); + data.pos += txt.length(); + + QStringList completions = getCompletions(data); + + QCOMPARE(completions.size(), 0); +} + +void CppToolsPlugin::test_completion_recursive_auto_declarations2_QTCREATORBUG9503() +{ + TestData data; + data.srcText = + "void f()\n" + "{\n" + " auto object3 = object1;\n" + " auto object2 = object3;\n" + " auto object1 = object2;\n" + " @;\n" + " // padding so we get the scope right\n" + "}\n" + ; + setup(&data); + + Utils::ChangeSet change; + QString txt = QLatin1String("object1."); + change.insert(data.pos, txt); + QTextCursor cursor(data.doc); + change.apply(&cursor); + data.pos += txt.length(); + + QStringList completions = getCompletions(data); + + QCOMPARE(completions.size(), 0); +} diff --git a/src/plugins/cpptools/cpptoolsplugin.h b/src/plugins/cpptools/cpptoolsplugin.h index bf9c9b67a5..0b3998c9e6 100644 --- a/src/plugins/cpptools/cpptoolsplugin.h +++ b/src/plugins/cpptools/cpptoolsplugin.h @@ -128,6 +128,8 @@ private slots: void test_completion_typedef_using_templates2(); void test_completion_namespace_alias_with_many_namespace_declarations(); void test_completion_crash_cloning_template_class_QTCREATORBUG9329(); + void test_completion_recursive_auto_declarations1_QTCREATORBUG9503(); + void test_completion_recursive_auto_declarations2_QTCREATORBUG9503(); void test_format_pointerdeclaration_in_simpledeclarations(); void test_format_pointerdeclaration_in_simpledeclarations_data(); |