C++: nested class with enclosing template class

The parent of instantiation of nested class of template class
should be the instantiation of enclosing template class.

To prevent the infinite loop for case with local typedef of enclosing
template we should not change a parent of typedefed instatiation of
enclosing template. Example:
template <typename T>
struct Enclosing
{
  typedef Enclosing<T> EnclosingT;// first case
  struct Nested
  {
    typedef Enclosing<T> EnclosingT;// second case
  };
};

Task-number: QTCREATORBUG-11752
Task-number: QTCREATORBUG-11999
Change-Id: Iadd7b5ef73ee0c4881f59c9dabfe03339f55827b
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com>
This commit is contained in:
Przemyslaw Gorszkowski
2014-04-30 09:07:57 +02:00
parent 0bc202d52f
commit ba42ceb0cb
2 changed files with 37 additions and 2 deletions

View File

@@ -88,6 +88,19 @@ static void path_helper(Symbol *symbol, QList<const Name *> *names)
} }
} }
static bool isNestedInstantiationEnclosingTemplate(
ClassOrNamespace *nestedClassOrNamespaceInstantiation,
ClassOrNamespace *enclosingTemplateClassInstantiation)
{
while (enclosingTemplateClassInstantiation) {
if (enclosingTemplateClassInstantiation == nestedClassOrNamespaceInstantiation)
return false;
enclosingTemplateClassInstantiation = enclosingTemplateClassInstantiation->parent();
}
return true;
}
namespace CPlusPlus { namespace CPlusPlus {
static inline bool compareName(const Name *name, const Name *other) static inline bool compareName(const Name *name, const Name *other)
@@ -1282,6 +1295,10 @@ void ClassOrNamespace::NestedClassInstantiator::instantiate(ClassOrNamespace *en
} }
} }
if (isNestedInstantiationEnclosingTemplate(nestedClassOrNamespaceInstantiation,
enclosingTemplateClass)) {
nestedClassOrNamespaceInstantiation->_parent = enclosingTemplateClassInstantiation;
}
instantiate(nestedClassOrNamespace, nestedClassOrNamespaceInstantiation); instantiate(nestedClassOrNamespace, nestedClassOrNamespaceInstantiation);
enclosingTemplateClassInstantiation->_classOrNamespaces[nestedName] = enclosingTemplateClassInstantiation->_classOrNamespaces[nestedName] =

View File

@@ -306,8 +306,6 @@ void CppToolsPlugin::test_completion()
expectedCompletions.sort(); expectedCompletions.sort();
QEXPECT_FAIL("enum_in_function_in_struct_in_function", "doesn't work", Abort); QEXPECT_FAIL("enum_in_function_in_struct_in_function", "doesn't work", Abort);
QEXPECT_FAIL("nested_class_in_template_class_QTCREATORBUG-11752",
"related to infiniteLoopLocalTypedef_QTCREATORBUG-11999", Abort);
QCOMPARE(actualCompletions, expectedCompletions); QCOMPARE(actualCompletions, expectedCompletions);
} }
@@ -2264,6 +2262,26 @@ void CppToolsPlugin::test_completion_data()
<< QLatin1String("foo") << QLatin1String("foo")
<< QLatin1String("Foo")); << QLatin1String("Foo"));
QTest::newRow("infiniteLoopLocalTypedef_QTCREATORBUG-11999") << _(
"template <typename T>\n"
"struct Temp\n"
"{\n"
" struct Nested\n"
" {\n"
" typedef Temp<T> TempT;\n"
" T t;\n"
" };\n"
" Nested nested;\n"
"};\n"
"struct Foo { int foo; };\n"
"void fun() {\n"
" Temp<Foo> tempFoo;\n"
" @\n"
"}\n"
) << _("tempFoo.nested.t.") << (QStringList()
<< QLatin1String("foo")
<< QLatin1String("Foo"));
QTest::newRow("lambda_parameter") << _( QTest::newRow("lambda_parameter") << _(
"auto func = [](int arg1) { return @; };\n" "auto func = [](int arg1) { return @; };\n"
) << _("ar") << (QStringList() ) << _("ar") << (QStringList()