Commit e58906a9 authored by Nikolai Kosjar's avatar Nikolai Kosjar

C++: Limit typedef resolving depth

This reverts commit 5be56c07 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: default avatarPrzemyslaw Gorszkowski <pgorszkowski@gmail.com>
Reviewed-by: default avatarErik Verbruggen <erik.verbruggen@digia.com>
parent c4c9b90b
......@@ -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();
......
......@@ -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 =
......
......@@ -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();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment