From e58906a9ed718b0e65a0f805c165e7bacf54d936 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar <nikolai.kosjar@digia.com> Date: Fri, 18 Oct 2013 10:25:52 +0200 Subject: [PATCH] C++: Limit typedef resolving depth This reverts commit 5be56c0 except for its tests. While it fixed the problem described in the bug report, it also introduced regressions. For now, we use a hard limit. Change-Id: I19a85be454e3d7969371707e3eb1c3d42a16ecee Reviewed-by: Przemyslaw Gorszkowski <pgorszkowski@gmail.com> Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com> --- src/libs/cplusplus/ResolveExpression.cpp | 33 ++----- src/plugins/cpptools/cppcompletion_test.cpp | 98 ++++++++++----------- src/plugins/cpptools/cpptoolsplugin.h | 5 +- 3 files changed, 57 insertions(+), 79 deletions(-) diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index fd144a4e611..fd29b1972bc 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 856f96d0049..3eed35b5074 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 2c30baf90fa..d9633708dc9 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(); -- GitLab