forked from qt-creator/qt-creator
C++: fix endless loop during template instantiation
This is the first phase of fixing bug QTCREATORBUG-10320.
This change resolves typedefs of template parameters(and resolves
problem with endless loop).
The next step will be matching appropriate template specialization
(this is needed to solve problem with missing code completion).
Missing matching: template specialization with the same parameters,
e.g.:
template <class T1, class T2, class T3>
class T
{
};
template <class T1, class T2>
class T<T1, T2, T2>
{
};
Task-number: QTCREATORBUG-10320
Change-Id: Icb6b539c021b2a67a66db9011a2e627f7d96526b
Reviewed-by: Przemyslaw Gorszkowski <pgorszkowski@gmail.com>
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com>
This commit is contained in:
committed by
Nikolai Kosjar
parent
0224ec0a64
commit
5be56c073e
@@ -887,6 +887,22 @@ 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);
|
||||
}
|
||||
QList<LookupItem> namedTypeItems = getNamedTypeItems(namedTy->name(), *scope, _binding);
|
||||
|
||||
#ifdef DEBUG_LOOKUP
|
||||
@@ -899,6 +915,16 @@ 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();
|
||||
|
||||
@@ -2740,6 +2740,55 @@ 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 =
|
||||
|
||||
@@ -184,6 +184,9 @@ 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();
|
||||
|
||||
Reference in New Issue
Block a user