Commit 077bbf68 authored by Filipp's avatar Filipp Committed by Nikolai Kosjar

search for partial specialization for arrays

A<int[]> now prefer second specialization for
template<typename T> class A
template<typename T> class A<[]>

Change-Id: I32e874f78b2f5b363d088fbab6a8897e42e44035
Reviewed-by: default avatarNikolai Kosjar <nikolai.kosjar@digia.com>
parent fa4e839b
......@@ -922,8 +922,31 @@ ClassOrNamespace *ClassOrNamespace::lookupType_helper(const Name *name,
return 0;
}
ClassOrNamespace *ClassOrNamespace::findSpecializationWithPointer(const TemplateNameId *templId,
const TemplateNameIdTable &specializations)
static ClassOrNamespace *findSpecializationWithMatchingTemplateArgument(const Name *argumentName,
ClassOrNamespace *reference)
{
foreach (Symbol *s, reference->symbols()) {
if (Class *clazz = s->asClass()) {
if (Template *templateSpecialization = clazz->enclosingTemplate()) {
const unsigned argumentCountOfSpecialization
= templateSpecialization->templateParameterCount();
for (unsigned i = 0; i < argumentCountOfSpecialization; ++i) {
if (TypenameArgument *tParam
= templateSpecialization->templateParameterAt(i)->asTypenameArgument()) {
if (const Name *name = tParam->name()) {
if (compareName(name, argumentName))
return reference;
}
}
}
}
}
}
return 0;
}
ClassOrNamespace *ClassOrNamespace::findSpecialization(const TemplateNameId *templId,
const TemplateNameIdTable &specializations)
{
// we go through all specialization and try to find that one with template argument as pointer
for (TemplateNameIdTable::const_iterator cit = specializations.begin();
......@@ -949,6 +972,21 @@ ClassOrNamespace *ClassOrNamespace::findSpecializationWithPointer(const Template
&& specPointer->elementType().type()->isNamedType()) {
return cit->second;
}
ArrayType *specArray
= specializationTemplateArgument.type()->asArrayType();
if (specArray && initializationTemplateArgument.type()->isArrayType()) {
if (const NamedType *argumentNamedType
= specArray->elementType().type()->asNamedType()) {
if (const Name *argumentName = argumentNamedType->name()) {
if (ClassOrNamespace *reference
= findSpecializationWithMatchingTemplateArgument(
argumentName, cit->second)) {
return reference;
}
}
}
}
}
}
}
......@@ -1026,7 +1064,7 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac
reference = cit->second;
} else {
ClassOrNamespace *specializationWithPointer
= findSpecializationWithPointer(templId, specializations);
= findSpecialization(templId, specializations);
if (specializationWithPointer)
reference = specializationWithPointer;
// TODO: find the best specialization(probably partial) for this instantiation
......
......@@ -128,8 +128,8 @@ private:
Subst &subst,
ClassOrNamespace *enclosingTemplateClassInstantiation);
bool isInstantiateNestedClassNeeded(const QList<Symbol *>& symbols, const Subst &subst) const;
ClassOrNamespace *findSpecializationWithPointer(const TemplateNameId *templId,
const TemplateNameIdTable &specializations);
ClassOrNamespace *findSpecialization(const TemplateNameId *templId,
const TemplateNameIdTable &specializations);
CreateBindings *_factory;
ClassOrNamespace *_parent;
......
......@@ -2353,6 +2353,45 @@ void CppToolsPlugin::test_completion_data()
) << _("arr[0]->") << (QStringList()
<< QLatin1String("foo")
<< QLatin1String("Foo"));
QTest::newRow("template_specialization_with_array1") << _(
"template <typename T>\n"
"struct S {};\n"
"template <typename T>\n"
"struct S<T[]> { int foo; };\n"
"void fun() {\n"
" S<int[]> s;\n"
" @\n"
"}\n"
) << _("s.") << (QStringList()
<< QLatin1String("foo")
<< QLatin1String("S"));
QTest::newRow("template_specialization_with_array2") << _(
"template <typename T>\n"
"struct S {};\n"
"template <typename T, size_t N>\n"
"struct S<T[N]> { int foo; };\n"
"void fun() {\n"
" S<int[3]> s;\n"
" @\n"
"}\n"
) << _("s.") << (QStringList()
<< QLatin1String("foo")
<< QLatin1String("S"));
QTest::newRow("template_specialization_with_array3") << _(
"struct Bar {};\n"
"template <typename T>\n"
"struct S {};\n"
"template <>\n"
"struct S<Bar[]> { int foo; };\n"
"void fun() {\n"
" S<int[]> s;\n"
" @\n"
"}\n"
) << _("s.") << (QStringList()
<< QLatin1String("S"));
}
void CppToolsPlugin::test_completion_member_access_operator()
......
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