Commit 50a900e5 authored by Nikolai Kosjar's avatar Nikolai Kosjar

C++: Handle recursive using/typedef declarations

Remember using/typedef declarations we have already looked up and
stop if we try it again.

Change-Id: I91bf0aef4df18539a47d015f0113543aef1f692a
Reviewed-by: default avatarErik Verbruggen <erik.verbruggen@digia.com>
parent 8f1b6656
...@@ -305,7 +305,8 @@ ClassOrNamespace *LookupContext::globalNamespace() const ...@@ -305,7 +305,8 @@ ClassOrNamespace *LookupContext::globalNamespace() const
} }
ClassOrNamespace *LookupContext::lookupType(const Name *name, Scope *scope, ClassOrNamespace *LookupContext::lookupType(const Name *name, Scope *scope,
ClassOrNamespace* enclosingTemplateInstantiation) const ClassOrNamespace* enclosingTemplateInstantiation,
QSet<const Declaration *> typedefsBeingResolved) const
{ {
if (! scope) { if (! scope) {
return 0; return 0;
...@@ -324,8 +325,14 @@ ClassOrNamespace *LookupContext::lookupType(const Name *name, Scope *scope, ...@@ -324,8 +325,14 @@ ClassOrNamespace *LookupContext::lookupType(const Name *name, Scope *scope,
Overview oo; Overview oo;
qDebug() << "Looks like" << oo(name) << "is a typedef for" << oo(d->type()); qDebug() << "Looks like" << oo(name) << "is a typedef for" << oo(d->type());
#endif // DEBUG_LOOKUP #endif // DEBUG_LOOKUP
if (const NamedType *namedTy = d->type()->asNamedType()) if (const NamedType *namedTy = d->type()->asNamedType()) {
return lookupType(namedTy->name(), scope); // Stop on recursive typedef declarations
if (typedefsBeingResolved.contains(d))
return 0;
return lookupType(namedTy->name(), scope, 0,
QSet<const Declaration *>(typedefsBeingResolved)
<< d);
}
} }
} }
} else if (UsingDeclaration *ud = m->asUsingDeclaration()) { } else if (UsingDeclaration *ud = m->asUsingDeclaration()) {
......
...@@ -289,7 +289,9 @@ public: ...@@ -289,7 +289,9 @@ public:
QList<LookupItem> lookup(const Name *name, Scope *scope) const; QList<LookupItem> lookup(const Name *name, Scope *scope) const;
ClassOrNamespace *lookupType(const Name *name, Scope *scope, ClassOrNamespace *lookupType(const Name *name, Scope *scope,
ClassOrNamespace* enclosingTemplateInstantiation = 0) const; ClassOrNamespace* enclosingTemplateInstantiation = 0,
QSet<const Declaration *> typedefsBeingResolved
= QSet<const Declaration *>()) const;
ClassOrNamespace *lookupType(Symbol *symbol, ClassOrNamespace *lookupType(Symbol *symbol,
ClassOrNamespace* enclosingTemplateInstantiation = 0) const; ClassOrNamespace* enclosingTemplateInstantiation = 0) const;
ClassOrNamespace *lookupParent(Symbol *symbol) const; ClassOrNamespace *lookupParent(Symbol *symbol) const;
......
...@@ -2326,3 +2326,140 @@ void CppToolsPlugin::test_completion_recursive_auto_declarations2_QTCREATORBUG95 ...@@ -2326,3 +2326,140 @@ void CppToolsPlugin::test_completion_recursive_auto_declarations2_QTCREATORBUG95
QCOMPARE(completions.size(), 0); QCOMPARE(completions.size(), 0);
} }
void CppToolsPlugin::test_completion_recursive_typedefs_declarations1()
{
TestData data;
data.srcText =
"void f()\n"
"{\n"
" typedef A B;\n"
" typedef B A;\n"
" A a;\n"
" @;\n"
" // padding so we get the scope right\n"
"}\n"
;
setup(&data);
Utils::ChangeSet change;
QString txt = QLatin1String("a.");
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_typedefs_declarations2()
{
TestData data;
data.srcText =
"void f()\n"
"{\n"
" typedef A C;\n"
" typedef C B;\n"
" typedef B A;\n"
" A a;\n"
" @;\n"
" // padding so we get the scope right\n"
"}\n"
;
setup(&data);
Utils::ChangeSet change;
QString txt = QLatin1String("a.");
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_using_declarations1()
{
TestData data;
data.srcText =
"void f()\n"
"{\n"
" using B = A;\n"
" using A = B;\n"
" A a;\n"
" @;\n"
" // padding so we get the scope right\n"
"}\n"
;
setup(&data);
Utils::ChangeSet change;
QString txt = QLatin1String("a.");
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_using_declarations2()
{
TestData data;
data.srcText =
"void f()\n"
"{\n"
" using C = A;\n"
" using B = C;\n"
" using A = B;\n"
" A a;\n"
" @;\n"
" // padding so we get the scope right\n"
"}\n"
;
setup(&data);
Utils::ChangeSet change;
QString txt = QLatin1String("a.");
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_using_typedef_declarations()
{
TestData data;
data.srcText =
"void f()\n"
"{\n"
" using B = A;\n"
" typedef B A;\n"
" A a;\n"
" @;\n"
" // padding so we get the scope right\n"
"}\n"
;
setup(&data);
Utils::ChangeSet change;
QString txt = QLatin1String("a.");
change.insert(data.pos, txt);
QTextCursor cursor(data.doc);
change.apply(&cursor);
data.pos += txt.length();
QStringList completions = getCompletions(data);
QCOMPARE(completions.size(), 0);
}
...@@ -140,6 +140,11 @@ private slots: ...@@ -140,6 +140,11 @@ private slots:
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_declarations1_QTCREATORBUG9503();
void test_completion_recursive_auto_declarations2_QTCREATORBUG9503(); void test_completion_recursive_auto_declarations2_QTCREATORBUG9503();
void test_completion_recursive_typedefs_declarations1();
void test_completion_recursive_typedefs_declarations2();
void test_completion_recursive_using_declarations1();
void test_completion_recursive_using_declarations2();
void test_completion_recursive_using_typedef_declarations();
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