aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNikolai Kosjar <nikolai.kosjar@digia.com>2013-10-18 10:25:52 +0200
committerNikolai Kosjar <nikolai.kosjar@digia.com>2013-10-18 14:07:00 +0200
commite58906a9ed718b0e65a0f805c165e7bacf54d936 (patch)
tree7b90dd84042d7452020cf8f7433b4c758f264f6e /src
parentc4c9b90b7f32b6b04026079ba5953bcf9730f562 (diff)
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>
Diffstat (limited to 'src')
-rw-r--r--src/libs/cplusplus/ResolveExpression.cpp33
-rw-r--r--src/plugins/cpptools/cppcompletion_test.cpp98
-rw-r--r--src/plugins/cpptools/cpptoolsplugin.h5
3 files changed, 57 insertions, 79 deletions
diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp
index fd144a4e61..fd29b1972b 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 856f96d004..3eed35b507 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 2c30baf90f..d9633708dc 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();