From ba42ceb0cb7827a9bbad29a1e08d4a25339ea57d Mon Sep 17 00:00:00 2001 From: Przemyslaw Gorszkowski Date: Wed, 30 Apr 2014 09:07:57 +0200 Subject: [PATCH] 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 struct Enclosing { typedef Enclosing EnclosingT;// first case struct Nested { typedef Enclosing EnclosingT;// second case }; }; Task-number: QTCREATORBUG-11752 Task-number: QTCREATORBUG-11999 Change-Id: Iadd7b5ef73ee0c4881f59c9dabfe03339f55827b Reviewed-by: Nikolai Kosjar --- src/libs/cplusplus/LookupContext.cpp | 17 ++++++++++++++++ src/plugins/cpptools/cppcompletion_test.cpp | 22 +++++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index 98050c911b6..3828babe790 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -88,6 +88,19 @@ static void path_helper(Symbol *symbol, QList *names) } } +static bool isNestedInstantiationEnclosingTemplate( + ClassOrNamespace *nestedClassOrNamespaceInstantiation, + ClassOrNamespace *enclosingTemplateClassInstantiation) +{ + while (enclosingTemplateClassInstantiation) { + if (enclosingTemplateClassInstantiation == nestedClassOrNamespaceInstantiation) + return false; + enclosingTemplateClassInstantiation = enclosingTemplateClassInstantiation->parent(); + } + + return true; +} + namespace CPlusPlus { 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); enclosingTemplateClassInstantiation->_classOrNamespaces[nestedName] = diff --git a/src/plugins/cpptools/cppcompletion_test.cpp b/src/plugins/cpptools/cppcompletion_test.cpp index e96c790c6c0..c1e03a84010 100644 --- a/src/plugins/cpptools/cppcompletion_test.cpp +++ b/src/plugins/cpptools/cppcompletion_test.cpp @@ -306,8 +306,6 @@ void CppToolsPlugin::test_completion() expectedCompletions.sort(); 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); } @@ -2264,6 +2262,26 @@ void CppToolsPlugin::test_completion_data() << QLatin1String("foo") << QLatin1String("Foo")); + QTest::newRow("infiniteLoopLocalTypedef_QTCREATORBUG-11999") << _( + "template \n" + "struct Temp\n" + "{\n" + " struct Nested\n" + " {\n" + " typedef Temp TempT;\n" + " T t;\n" + " };\n" + " Nested nested;\n" + "};\n" + "struct Foo { int foo; };\n" + "void fun() {\n" + " Temp tempFoo;\n" + " @\n" + "}\n" + ) << _("tempFoo.nested.t.") << (QStringList() + << QLatin1String("foo") + << QLatin1String("Foo")); + QTest::newRow("lambda_parameter") << _( "auto func = [](int arg1) { return @; };\n" ) << _("ar") << (QStringList()