diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index ef4a766fd705e3ae93a8f31d770002491576965e..0364b59c725471a7d077c5ab8bc6794b7465c11c 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -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); } } } diff --git a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp index 6f98752d46087379f11069f81c3f4b28d3fe2757..956b02b5d980735ac1507bb7514cfa9c39f401b1 100644 --- a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp +++ b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp @@ -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); diff --git a/src/plugins/cpptools/cppcompletion_test.cpp b/src/plugins/cpptools/cppcompletion_test.cpp index 15a1a43de9ed3f008b7c48596aeae2b54a5a0caf..8dbb838c9998e07e563793a5fa610e218157b25f 100644 --- a/src/plugins/cpptools/cppcompletion_test.cpp +++ b/src/plugins/cpptools/cppcompletion_test.cpp @@ -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); } diff --git a/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp b/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp index b343b99357bb2726fa7ce3896b1f3bd2c3f32d94..57c9f33823256718b8653a6243d6915a500e0f9f 100644 --- a/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp +++ b/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp @@ -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); }