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);
 }