Commit 8f1b6656 authored by Nikolai Kosjar's avatar Nikolai Kosjar

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: default avatarPrzemyslaw Gorszkowski <pgorszkowski@gmail.com>
Reviewed-by: default avatarErik Verbruggen <erik.verbruggen@digia.com>
parent f1ed40a0
...@@ -77,11 +77,13 @@ static QList<_Tp> removeDuplicates(const QList<_Tp> &results) ...@@ -77,11 +77,13 @@ static QList<_Tp> removeDuplicates(const QList<_Tp> &results)
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
// ResolveExpression // ResolveExpression
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
ResolveExpression::ResolveExpression(const LookupContext &context) ResolveExpression::ResolveExpression(const LookupContext &context,
const QSet<const Declaration *> &autoDeclarationsBeingResolved)
: ASTVisitor(context.expressionDocument()->translationUnit()), : ASTVisitor(context.expressionDocument()->translationUnit()),
_scope(0), _scope(0),
_context(context), _context(context),
bind(context.expressionDocument()->translationUnit()), bind(context.expressionDocument()->translationUnit()),
_autoDeclarationsBeingResolved(autoDeclarationsBeingResolved),
_reference(false) _reference(false)
{ } { }
...@@ -521,6 +523,10 @@ bool ResolveExpression::visit(SimpleNameAST *ast) ...@@ -521,6 +523,10 @@ bool ResolveExpression::visit(SimpleNameAST *ast)
if (!decl) if (!decl)
continue; continue;
// Stop on recursive auto declarations
if (_autoDeclarationsBeingResolved.contains(decl))
continue;
const StringLiteral *initializationString = decl->getInitializer(); const StringLiteral *initializationString = decl->getInitializer();
if (initializationString == 0) if (initializationString == 0)
continue; continue;
...@@ -535,7 +541,8 @@ bool ResolveExpression::visit(SimpleNameAST *ast) ...@@ -535,7 +541,8 @@ bool ResolveExpression::visit(SimpleNameAST *ast)
TypeOfExpression exprTyper; TypeOfExpression exprTyper;
Document::Ptr doc = _context.snapshot().document(QString::fromLocal8Bit(decl->fileName())); 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 = Document::Ptr exprDoc =
documentForExpression(exprTyper.preprocessedExpression(initializer)); documentForExpression(exprTyper.preprocessedExpression(initializer));
...@@ -545,8 +552,8 @@ bool ResolveExpression::visit(SimpleNameAST *ast) ...@@ -545,8 +552,8 @@ bool ResolveExpression::visit(SimpleNameAST *ast)
if (deduceAuto._block) if (deduceAuto._block)
continue; continue;
const QList<LookupItem> &typeItems = const QList<LookupItem> &typeItems = exprTyper(extractExpressionAST(exprDoc), exprDoc,
exprTyper(extractExpressionAST(exprDoc), exprDoc, decl->enclosingScope()); decl->enclosingScope());
if (typeItems.empty()) if (typeItems.empty())
continue; continue;
......
...@@ -43,7 +43,9 @@ namespace CPlusPlus { ...@@ -43,7 +43,9 @@ namespace CPlusPlus {
class CPLUSPLUS_EXPORT ResolveExpression: protected ASTVisitor class CPLUSPLUS_EXPORT ResolveExpression: protected ASTVisitor
{ {
public: public:
ResolveExpression(const LookupContext &context); ResolveExpression(const LookupContext &context,
const QSet<const Declaration *> &autoDeclarationsBeingResolved
= QSet<const Declaration *>());
virtual ~ResolveExpression(); virtual ~ResolveExpression();
QList<LookupItem> operator()(ExpressionAST *ast, Scope *scope); QList<LookupItem> operator()(ExpressionAST *ast, Scope *scope);
...@@ -126,6 +128,7 @@ private: ...@@ -126,6 +128,7 @@ private:
const LookupContext& _context; const LookupContext& _context;
Bind bind; Bind bind;
QList<LookupItem> _results; QList<LookupItem> _results;
QSet<const Declaration *> _autoDeclarationsBeingResolved;
bool _reference; bool _reference;
}; };
......
...@@ -60,7 +60,8 @@ void TypeOfExpression::reset() ...@@ -60,7 +60,8 @@ void TypeOfExpression::reset()
} }
void TypeOfExpression::init(Document::Ptr thisDocument, const Snapshot &snapshot, void TypeOfExpression::init(Document::Ptr thisDocument, const Snapshot &snapshot,
QSharedPointer<CreateBindings> bindings) QSharedPointer<CreateBindings> bindings,
const QSet<const Declaration *> &autoDeclarationsBeingResolved)
{ {
m_thisDocument = thisDocument; m_thisDocument = thisDocument;
m_snapshot = snapshot; m_snapshot = snapshot;
...@@ -69,6 +70,7 @@ void TypeOfExpression::init(Document::Ptr thisDocument, const Snapshot &snapshot ...@@ -69,6 +70,7 @@ void TypeOfExpression::init(Document::Ptr thisDocument, const Snapshot &snapshot
m_lookupContext = LookupContext(); m_lookupContext = LookupContext();
m_bindings = bindings; m_bindings = bindings;
m_environment.clear(); m_environment.clear();
m_autoDeclarationsBeingResolved = autoDeclarationsBeingResolved;
} }
QList<LookupItem> TypeOfExpression::operator()(const QByteArray &utf8code, QList<LookupItem> TypeOfExpression::operator()(const QByteArray &utf8code,
...@@ -113,7 +115,7 @@ QList<LookupItem> TypeOfExpression::operator()(ExpressionAST *expression, ...@@ -113,7 +115,7 @@ QList<LookupItem> TypeOfExpression::operator()(ExpressionAST *expression,
m_lookupContext.setBindings(m_bindings); m_lookupContext.setBindings(m_bindings);
m_lookupContext.setExpandTemplates(m_expandTemplates); m_lookupContext.setExpandTemplates(m_expandTemplates);
ResolveExpression resolve(m_lookupContext); ResolveExpression resolve(m_lookupContext, m_autoDeclarationsBeingResolved);
const QList<LookupItem> items = resolve(m_ast, scope); const QList<LookupItem> items = resolve(m_ast, scope);
if (! m_bindings) if (! m_bindings)
...@@ -135,7 +137,7 @@ QList<LookupItem> TypeOfExpression::reference(ExpressionAST *expression, ...@@ -135,7 +137,7 @@ QList<LookupItem> TypeOfExpression::reference(ExpressionAST *expression,
m_lookupContext.setBindings(m_bindings); m_lookupContext.setBindings(m_bindings);
m_lookupContext.setExpandTemplates(m_expandTemplates); m_lookupContext.setExpandTemplates(m_expandTemplates);
ResolveExpression resolve(m_lookupContext); ResolveExpression resolve(m_lookupContext, m_autoDeclarationsBeingResolved);
const QList<LookupItem> items = resolve.reference(m_ast, scope); const QList<LookupItem> items = resolve.reference(m_ast, scope);
if (! m_bindings) if (! m_bindings)
......
...@@ -59,8 +59,11 @@ public: ...@@ -59,8 +59,11 @@ public:
* Also clears the lookup context, so can be used to make sure references * Also clears the lookup context, so can be used to make sure references
* to the documents previously used are removed. * to the documents previously used are removed.
*/ */
void init(Document::Ptr thisDocument, const Snapshot &snapshot, void init(Document::Ptr thisDocument,
QSharedPointer<CreateBindings> bindings = QSharedPointer<CreateBindings>()); const Snapshot &snapshot,
QSharedPointer<CreateBindings> bindings = QSharedPointer<CreateBindings>(),
const QSet<const Declaration *> &autoDeclarationsBeingResolved
= QSet<const Declaration *>());
void reset(); void reset();
...@@ -152,6 +155,8 @@ private: ...@@ -152,6 +155,8 @@ private:
// Keep the expression documents and thus all the symbols and // Keep the expression documents and thus all the symbols and
// their types alive until they are not needed any more. // their types alive until they are not needed any more.
QList<Document::Ptr> m_documents; QList<Document::Ptr> m_documents;
QSet<const Declaration *> m_autoDeclarationsBeingResolved;
}; };
ExpressionAST CPLUSPLUS_EXPORT *extractExpressionAST(Document::Ptr doc); ExpressionAST CPLUSPLUS_EXPORT *extractExpressionAST(Document::Ptr doc);
......
...@@ -2273,3 +2273,56 @@ void CppToolsPlugin::test_completion_crash_cloning_template_class_QTCREATORBUG93 ...@@ -2273,3 +2273,56 @@ void CppToolsPlugin::test_completion_crash_cloning_template_class_QTCREATORBUG93
QVERIFY(completions.contains(QLatin1String("Templ"))); QVERIFY(completions.contains(QLatin1String("Templ")));
QVERIFY(completions.contains(QLatin1String("f"))); 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);
}
...@@ -138,6 +138,8 @@ private slots: ...@@ -138,6 +138,8 @@ private slots:
void test_completion_instantiate_template_with_anonymous_class(); void test_completion_instantiate_template_with_anonymous_class();
void test_completion_instantiate_template_function(); void test_completion_instantiate_template_function();
void test_completion_crash_cloning_template_class_QTCREATORBUG9329(); 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();
void test_format_pointerdeclaration_in_simpledeclarations_data(); void test_format_pointerdeclaration_in_simpledeclarations_data();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment