Commit 915f68de authored by Nikolai Kosjar's avatar Nikolai Kosjar Committed by Eike Ziller

C++: Revert problematic template specialization changes

This mainly reverts

    commit 81721f67
    C++: Fix resolving of recursive typedef

    commit 2070431d
    C++: Fix resolving of partial specialization

and some bits of other changes due to dependencies. It also reverts

    commit e0594fc9
    C++: Fix expensive lookup for boost

which attempted to solve the upcoming problems.

Task-number: QTCREATORBUG-14741
Task-number: QTCREATORBUG-14889
Task-number: QTCREATORBUG-14962
Change-Id: I3f9e1f97199e5199b71da394fc27051c7709bd1f
Reviewed-by: Orgad Shaneh's avatarOrgad Shaneh <orgads@gmail.com>
Reviewed-by: default avatarEike Ziller <eike.ziller@theqtcompany.com>
parent a2bd8e11
......@@ -570,7 +570,7 @@ private:
LookupScopePrivate *nestedType(const Name *name, LookupScopePrivate *origin);
LookupScopePrivate *findSpecialization(const Template *baseTemplate, const TemplateNameId *templId,
LookupScopePrivate *findSpecialization(const TemplateNameId *templId,
const TemplateNameIdTable &specializations,
LookupScopePrivate *origin);
......@@ -1001,11 +1001,13 @@ LookupScope *LookupScopePrivate::lookupType_helper(
}
if (const QualifiedNameId *qName = name->asQualifiedNameId()) {
ProcessedSet innerProcessed;
if (! qName->base())
return globalNamespace()->d->lookupType_helper(qName->name(), processed, true, origin);
return globalNamespace()->d->lookupType_helper(qName->name(), &innerProcessed, true, origin);
if (LookupScope *binding = lookupType_helper(qName->base(), processed, true, origin))
return binding->d->lookupType_helper(qName->name(), processed, false, origin);
return binding->d->lookupType_helper(qName->name(), &innerProcessed, false, origin);
return 0;
......@@ -1017,7 +1019,7 @@ LookupScope *LookupScopePrivate::lookupType_helper(
foreach (Symbol *s, _symbols) {
if (Class *klass = s->asClass()) {
if (klass->name() && klass->name()->match(name))
if (klass->identifier() && klass->identifier()->match(name->identifier()))
return q;
}
}
......@@ -1051,29 +1053,9 @@ LookupScope *LookupScopePrivate::lookupType_helper(
return 0;
}
static const NamedType *dereference(const FullySpecifiedType &type)
static LookupScopePrivate *findSpecializationWithMatchingTemplateArgument(
const Name *argumentName, LookupScopePrivate *reference)
{
FullySpecifiedType ty = type;
forever {
if (PointerType *pointer = ty->asPointerType())
ty = pointer->elementType();
else if (ReferenceType *reference = ty->asReferenceType())
ty = reference->elementType();
else if (ArrayType *array = ty->asArrayType())
ty = array->elementType();
else if (const NamedType *namedType = ty->asNamedType())
return namedType;
else
break;
}
return 0;
}
static bool findTemplateArgument(const NamedType *namedType, LookupScopePrivate *reference)
{
if (!namedType)
return false;
const Name *argumentName = namedType->name();
foreach (Symbol *s, reference->_symbols) {
if (Class *clazz = s->asClass()) {
if (Template *templateSpecialization = clazz->enclosingTemplate()) {
......@@ -1084,67 +1066,67 @@ static bool findTemplateArgument(const NamedType *namedType, LookupScopePrivate
= templateSpecialization->templateParameterAt(i)->asTypenameArgument()) {
if (const Name *name = tParam->name()) {
if (compareName(name, argumentName))
return true;
return reference;
}
}
}
}
}
}
return false;
}
static bool matchTypes(const FullySpecifiedType &instantiation,
const FullySpecifiedType &specialization)
{
if (specialization.match(instantiation))
return true;
if (const NamedType *specName = specialization->asNamedType()) {
if (const NamedType *initName = instantiation->asNamedType()) {
if (specName->name()->identifier()->match(initName->name()->identifier()))
return true;
}
}
return false;
return 0;
}
LookupScopePrivate *LookupScopePrivate::findSpecialization(
const Template *baseTemplate,
const TemplateNameId *templId,
const TemplateNameIdTable &specializations,
LookupScopePrivate *origin)
{
Clone cloner(_factory->control().data());
for (TemplateNameIdTable::const_iterator cit = specializations.begin();
cit != specializations.end(); ++cit) {
const TemplateNameId *specializationNameId = cit->first;
const unsigned specializationTemplateArgumentCount
= specializationNameId->templateArgumentCount();
Subst subst(_factory->control().data());
bool match = true;
for (unsigned i = 0; i < specializationTemplateArgumentCount && match; ++i) {
const unsigned initializationTemplateArgumentCount = templId->templateArgumentCount();
// for now it works only when we have the same number of arguments in specialization
// and initialization(in future it should be more clever)
if (specializationTemplateArgumentCount != initializationTemplateArgumentCount)
continue;
for (unsigned i = 0; i < initializationTemplateArgumentCount; ++i) {
const FullySpecifiedType &specializationTemplateArgument
= specializationNameId->templateArgumentAt(i);
FullySpecifiedType initializationTemplateArgument =
_factory->resolveTemplateArgument(cloner, subst, origin ? origin->q : 0,
baseTemplate, templId, i);
FullySpecifiedType initializationTemplateArgument = templId->templateArgumentAt(i);
TypeResolver typeResolver(*_factory);
Scope *scope = 0;
typeResolver.resolve(&initializationTemplateArgument, &scope, origin ? origin->q : 0);
PointerType *specPointer = specializationTemplateArgument.type()->asPointerType();
// specialization and initialization argument have to be a pointer
// additionally type of pointer argument of specialization has to be namedType
if (findTemplateArgument(dereference(specializationTemplateArgument), cit->second)) {
if (specializationTemplateArgument->isPointerType())
match = initializationTemplateArgument->isPointerType();
else if (specializationTemplateArgument->isReferenceType())
match = initializationTemplateArgument->isReferenceType();
else if (specializationTemplateArgument->isArrayType())
match = initializationTemplateArgument->isArrayType();
// Do not try exact match (typename T != class T {};)
} else {
// Real type specialization
match = matchTypes(initializationTemplateArgument, specializationTemplateArgument);
if (specPointer && initializationTemplateArgument.type()->isPointerType()
&& 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 (LookupScopePrivate *reference
= findSpecializationWithMatchingTemplateArgument(
argumentName, cit->second)) {
return reference;
}
}
}
}
if (const NamedType *specName = specializationTemplateArgument->asNamedType()) {
if (const NamedType *initName = initializationTemplateArgument->asNamedType()) {
if (specName->name()->identifier() == initName->name()->identifier())
return cit->second;
}
}
}
if (match)
return cit->second;
}
return 0;
......@@ -1245,23 +1227,12 @@ LookupScopePrivate *LookupScopePrivate::nestedType(const Name *name, LookupScope
// we found full specialization
reference = cit->second;
} else {
Template *baseTemplate = 0;
foreach (Symbol *s, reference->_symbols) {
if (Class *clazz = s->asClass())
baseTemplate = clazz->enclosingTemplate();
else if (ForwardClassDeclaration *forward = s->asForwardClassDeclaration())
baseTemplate = forward->enclosingTemplate();
if (baseTemplate)
break;
}
if (baseTemplate) {
if (LookupScopePrivate *specialization =
findSpecialization(baseTemplate, templId, specializations, origin)) {
reference = specialization;
if (Q_UNLIKELY(debug)) {
Overview oo;
qDebug() << "picked specialization" << oo(specialization->_name);
}
if (LookupScopePrivate *specialization =
findSpecialization(templId, specializations, origin)) {
reference = specialization;
if (Q_UNLIKELY(debug)) {
Overview oo;
qDebug() << "picked specialization" << oo(specialization->_name);
}
}
}
......
......@@ -369,7 +369,6 @@ F2TestCase::F2TestCase(CppEditorAction action,
QEXPECT_FAIL("globalVarFromEnum", "Contributor works on a fix.", Abort);
QEXPECT_FAIL("matchFunctionSignature_Follow_5", "foo(int) resolved as CallAST", Abort);
QEXPECT_FAIL("qualifiedNames", "Regression since e0594fc9b906a32f5c8ac70265490cf86044676f", Abort);
QCOMPARE(currentTextEditor->currentLine(), expectedLine);
QCOMPARE(currentTextEditor->currentColumn() - 1, expectedColumn);
......
......@@ -328,11 +328,16 @@ void CppToolsPlugin::test_completion()
QEXPECT_FAIL("template_as_base: typedef not available in derived",
"We can live with that...", Abort);
QEXPECT_FAIL("template_specialization_with_reference", "test of reverted change", Abort);
QEXPECT_FAIL("specialization_multiple_arguments", "test of reverted change", Abort);
QEXPECT_FAIL("specialization_with_default_value", "test of reverted change", Abort);
QEXPECT_FAIL("partial_specialization_with_pointer", "test of reverted change", Abort);
QEXPECT_FAIL("enum_in_function_in_struct_in_function", "QTCREATORBUG-13757", Abort);
QEXPECT_FAIL("enum_in_function_in_struct_in_function_cxx11", "QTCREATORBUG-13757", Abort);
QEXPECT_FAIL("enum_in_function_in_struct_in_function_anon", "QTCREATORBUG-13757", Abort);
QEXPECT_FAIL("enum_in_class_accessed_in_member_func_cxx11", "QTCREATORBUG-13757", Abort);
QEXPECT_FAIL("enum_in_class_accessed_in_member_func_inline_cxx11", "QTCREATORBUG-13757", Abort);
QEXPECT_FAIL("recursive_instantiation_of_template_type", "QTCREATORBUG-14237", Abort);
QCOMPARE(actualCompletions, expectedCompletions);
}
......
......@@ -1213,7 +1213,7 @@ void tst_CheckSymbols::findField()
BaseTestCase tc(source);
Use use = tc.findUse(line, column);
QEXPECT_FAIL("std vector", "Regression since e0594fc9b906a32f5c8ac70265490cf86044676f", Abort);
QEXPECT_FAIL("recursive_instantiation_of_template_type", "QTCREATORBUG-14237", Abort);
QVERIFY(use.isValid());
QVERIFY(use.kind == Highlighting::FieldUse);
}
......
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