diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index fd144a4e611620411f22f0ad0b30b3e1256b1a97..fd29b1972bc4f3f8bbbc2d04268fcdbb97cd42ed 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -886,23 +886,12 @@ public: { QSet<Symbol *> visited; _binding = binding; - while (NamedType *namedTy = getNamedType(*type)) { - const Name *name = namedTy->name(); - Scope *templateScope = *scope; - if (const QualifiedNameId *q = name->asQualifiedNameId()) { - do { - const TemplateNameId *templateNameId = 0; - name = q->name(); - if (name && (templateNameId = name->asTemplateNameId())) - resolve(templateNameId, templateScope, binding); - - name = q->base(); - if (name && (templateNameId = name->asTemplateNameId())) - resolve(templateNameId, templateScope, binding); - } while ((name && (q = name->asQualifiedNameId()))); - } else if (const TemplateNameId *templateNameId = name->asTemplateNameId()) { - resolve(templateNameId, templateScope, binding); - } + // Use a hard limit when trying to resolve typedefs. Typedefs in templates can refer to + // each other, each time enhancing the template argument and thus making it impossible to + // use an "alreadyResolved" container. FIXME: We might overcome this by resolving the + // template parameters. + unsigned maxDepth = 15; + for (NamedType *namedTy = 0; maxDepth && (namedTy = getNamedType(*type)); --maxDepth) { QList<LookupItem> namedTypeItems = getNamedTypeItems(namedTy->name(), *scope, _binding); #ifdef DEBUG_LOOKUP @@ -915,16 +904,6 @@ public: } private: - void resolve(const TemplateNameId *templateNameId, Scope *templateScope, - ClassOrNamespace *binding) - { - for (unsigned i = 0; i < templateNameId->templateArgumentCount(); ++i) { - FullySpecifiedType &templateArgumentType - = const_cast<FullySpecifiedType &>(templateNameId->templateArgumentAt(i)); - resolve(&templateArgumentType, &templateScope, binding); - } - } - NamedType *getNamedType(FullySpecifiedType& type) const { NamedType *namedTy = type->asNamedType(); diff --git a/src/plugins/cpptools/cppcompletion_test.cpp b/src/plugins/cpptools/cppcompletion_test.cpp index 856f96d0049930a49ed5e54a0e27403b4dcc1cf3..3eed35b50743036bc17d6303e27454f9a982d1fa 100644 --- a/src/plugins/cpptools/cppcompletion_test.cpp +++ b/src/plugins/cpptools/cppcompletion_test.cpp @@ -2070,6 +2070,55 @@ void CppToolsPlugin::test_completion_recursive_using_typedef_declarations() QCOMPARE(completions.size(), 0); } +void CppToolsPlugin::test_completion_recursive_typedefs_in_templates1() +{ + const QByteArray source = + "template<typename From>\n" + "struct simplify_type {\n" + " typedef From SimpleType;\n" + "};\n" + "\n" + "template<class To, class From>\n" + "struct cast_retty {\n" + " typedef typename cast_retty_wrap<To, From,\n" + " typename simplify_type<From>::SimpleType>::ret_type ret_type;\n" + "};\n" + "\n" + "template<class To, class From, class SimpleFrom>\n" + "struct cast_retty_wrap {\n" + " typedef typename cast_retty<To, SimpleFrom>::ret_type ret_type;\n" + "};\n" + "\n" + "void f()\n" + "{\n" + " @;\n" + "}\n" + ; + CompletionTestCase test(source, "cast_retty<T1, T2>::ret_type."); + + const QStringList completions = test.getCompletions(); + QCOMPARE(completions.size(), 0); +} + +void CppToolsPlugin::test_completion_recursive_typedefs_in_templates2() +{ + const QByteArray source = + "template<class T>\n" + "struct recursive {\n" + " typedef typename recursive<T>::ret_type ret_type;\n" + "};\n" + "\n" + "void f()\n" + "{\n" + " @;\n" + "}\n" + ; + CompletionTestCase test(source, "recursive<T1>::ret_type.foo"); + + const QStringList completions = test.getCompletions(); + QCOMPARE(completions.size(), 0); +} + void CppToolsPlugin::test_completion_prefix_first_QTCREATORBUG_8737() { const QByteArray source = @@ -2740,55 +2789,6 @@ void CppToolsPlugin::test_completion_template_parameter_defined_inside_scope_of_ QVERIFY(completions.contains(QLatin1String("bar"))); } -void CppToolsPlugin::test_completion_recursive_typedefs_in_templates1() -{ - const QByteArray source = - "template<typename From>\n" - "struct simplify_type {\n" - " typedef From SimpleType;\n" - "};\n" - "\n" - "template<class To, class From>\n" - "struct cast_retty {\n" - " typedef typename cast_retty_wrap<To, From,\n" - " typename simplify_type<From>::SimpleType>::ret_type ret_type;\n" - "};\n" - "\n" - "template<class To, class From, class SimpleFrom>\n" - "struct cast_retty_wrap {\n" - " typedef typename cast_retty<To, SimpleFrom>::ret_type ret_type;\n" - "};\n" - "\n" - "void f()\n" - "{\n" - " @;\n" - "}\n" - ; - CompletionTestCase test(source, "cast_retty<T1, T2>::ret_type."); - - const QStringList completions = test.getCompletions(); - QCOMPARE(completions.size(), 0); -} - -void CppToolsPlugin::test_completion_recursive_typedefs_in_templates2() -{ - const QByteArray source = - "template<class T>\n" - "struct recursive {\n" - " typedef typename recursive<To>::ret_type ret_type;\n" - "};\n" - "\n" - "void f()\n" - "{\n" - " @;\n" - "}\n" - ; - CompletionTestCase test(source, "recursive<T1>::ret_type.foo"); - - const QStringList completions = test.getCompletions(); - QCOMPARE(completions.size(), 0); -} - void CppToolsPlugin::test_completion_signals_hide_QPrivateSignal() { const QByteArray source = diff --git a/src/plugins/cpptools/cpptoolsplugin.h b/src/plugins/cpptools/cpptoolsplugin.h index 2c30baf90fa87d76bfe8882971df914943ea5b1f..d9633708dc91d523bcdba2ed39823d5b2514af1f 100644 --- a/src/plugins/cpptools/cpptoolsplugin.h +++ b/src/plugins/cpptools/cpptoolsplugin.h @@ -153,6 +153,8 @@ private slots: void test_completion_recursive_using_declarations1(); void test_completion_recursive_using_declarations2(); void test_completion_recursive_using_typedef_declarations(); + void test_completion_recursive_typedefs_in_templates1(); + void test_completion_recursive_typedefs_in_templates2(); void test_completion_prefix_first_QTCREATORBUG_8737(); void test_completion_prefix_first_QTCREATORBUG_9236(); @@ -184,9 +186,6 @@ private slots: void test_completion_local_type_and_member_5(); void test_completion_local_type_and_member_6(); - void test_completion_recursive_typedefs_in_templates1(); - void test_completion_recursive_typedefs_in_templates2(); - void test_completion_signals_hide_QPrivateSignal(); void test_format_pointerdeclaration_in_simpledeclarations();