diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp
index dde50df687f772a0f29bc34e9572bb3e61f67fe0..6df4b43cf36e93435fd48d6237427319e4d12180 100644
--- a/src/libs/cplusplus/LookupContext.cpp
+++ b/src/libs/cplusplus/LookupContext.cpp
@@ -719,10 +719,43 @@ ClassOrNamespace *ClassOrNamespace::lookupType_helper(const Name *name,
         if (name->isNameId() || name->isTemplateNameId() || name->isAnonymousNameId()) {
             flush();
 
+            if (name->isTemplateNameId()) {
+                // if it is a base specialization, the 'name' could be an instantiation
+                QMap<const TemplateNameId *, ClassOrNamespace *>::iterator it
+                        = _instantiations.find(name->asTemplateNameId());
+                if (it != _instantiations.end())
+                    return it.value();
+            }
+
             foreach (Symbol *s, symbols()) {
                 if (Class *klass = s->asClass()) {
                     if (klass->identifier() && klass->identifier()->isEqualTo(name->identifier()))
                         return this;
+
+                    // it can be a typedef
+                    const unsigned memberClassCount = klass->memberCount();
+                    for (unsigned i = 0; i < memberClassCount; ++i) {
+                        Symbol *memberClassAsSymbol = klass->memberAt(i);
+                        if (Declaration *declaration = memberClassAsSymbol->asDeclaration()) {
+                            if (declaration->isTypedef()
+                                    && name->identifier()->isEqualTo(declaration->name()->identifier
+                                                                     ())) {
+                                if (NamedType *namedType = declaration->type()->asNamedType()) {
+                                    QSet<ClassOrNamespace *> innerProcessed;
+                                    const Name *namedTypeName = namedType->name();
+                                    const QualifiedNameId *q = namedTypeName->asQualifiedNameId();
+                                    if (q && name->isEqualTo(q->base())
+                                            && name->isEqualTo(q->name())) {
+                                        return lookupType_helper_inParent(name, &innerProcessed,
+                                                                          searchInEnclosingScope,
+                                                                          origin);
+                                    }
+                                    return lookupType_helper(namedTypeName, &innerProcessed,
+                                                             true, origin);
+                                }
+                            }
+                        }
+                    }
                 }
             }
 
@@ -746,6 +779,9 @@ ClassOrNamespace *ClassOrNamespace::lookupType_helper(const Name *name,
             }
 
             foreach (ClassOrNamespace *u, usings()) {
+                // usings are not instantiated for templates
+                if (_templateId && u->_templateId)
+                    continue;
                 if (ClassOrNamespace *r = u->lookupType_helper(name,
                                                                processed,
                                                                /*searchInEnclosingScope =*/ false,
@@ -754,8 +790,21 @@ ClassOrNamespace *ClassOrNamespace::lookupType_helper(const Name *name,
             }
         }
 
-        if (_parent && searchInEnclosingScope)
-            return _parent->lookupType_helper(name, processed, searchInEnclosingScope, origin);
+        return lookupType_helper_inParent(name, processed, searchInEnclosingScope, origin);
+    }
+
+    return 0;
+}
+
+ClassOrNamespace *ClassOrNamespace::lookupType_helper_inParent(const Name *name, QSet<ClassOrNamespace *> *processed,
+                                                               bool searchInEnclosingScope, ClassOrNamespace *origin)
+{
+    if (_parent && searchInEnclosingScope) {
+        // for templates _parent is a base specialization,
+        // so we should take here rather _parent of this base specialization
+        ClassOrNamespace *parent = _templateId ? _parent->_parent : _parent;
+        if (parent)
+            return parent->lookupType_helper(name, processed, searchInEnclosingScope, origin);
     }
 
     return 0;
@@ -959,7 +1008,7 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac
                     oo.showReturnTypes = true;
                     oo.showTemplateParameters = true;
                     qDebug()<<"cloned"<<oo(clone->type());
-                    if (Class *klass = s->asClass()) {
+                    if (Class *klass = clone->asClass()) {
                         const unsigned klassMemberCount = klass->memberCount();
                         for (unsigned i = 0; i < klassMemberCount; ++i){
                             Symbol *klassMemberAsSymbol = klass->memberAt(i);
diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h
index 3dbe525766a3c4656660ff0a1a51eeea9fd108c9..d1e64cdd87f5be723ac9ffa0274e47f9dc9c70e2 100644
--- a/src/libs/cplusplus/LookupContext.h
+++ b/src/libs/cplusplus/LookupContext.h
@@ -111,6 +111,9 @@ private:
     ClassOrNamespace *lookupType_helper(const Name *name, QSet<ClassOrNamespace *> *processed,
                                         bool searchInEnclosingScope, ClassOrNamespace *origin);
 
+    ClassOrNamespace *lookupType_helper_inParent(const Name *name, QSet<ClassOrNamespace *> *processed,
+                                        bool searchInEnclosingScope, ClassOrNamespace *origin);
+
     ClassOrNamespace *nestedType(const Name *name, ClassOrNamespace *origin);
 
     void instantiateNestedClasses(ClassOrNamespace *enclosingTemplateClass,
diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp
index 029bcee00d43092ed6eb6d16d3e36aa26325cef1..8a72fc1fc2a70ff8f1c9872dad05a925edcc9c55 100644
--- a/src/libs/cplusplus/ResolveExpression.cpp
+++ b/src/libs/cplusplus/ResolveExpression.cpp
@@ -690,8 +690,15 @@ bool ResolveExpression::visit(CallAST *ast)
             }
 
         } else if (Function *funTy = ty->asFunctionType()) {
-            if (maybeValidPrototype(funTy, actualArgumentCount))
-                addResult(funTy->returnType().simplified(), scope);
+            if (maybeValidPrototype(funTy, actualArgumentCount)) {
+                LookupItem item;
+                item.setType(funTy->returnType().simplified());
+                item.setScope(scope);
+                // we have to remember a binding because it can be a template instantiation
+                item.setBinding(result.binding());
+
+                _results.append(item);
+            }
 
         } else if (Class *classTy = ty->asClassType()) {
             // Constructor call
diff --git a/src/plugins/cpptools/cppcompletion_test.cpp b/src/plugins/cpptools/cppcompletion_test.cpp
index b8ee95f7c04a879581c8f3f4cd4c94cc39cc6535..70a5469b1234d911f8d3d29213bea818dedbf89c 100644
--- a/src/plugins/cpptools/cppcompletion_test.cpp
+++ b/src/plugins/cpptools/cppcompletion_test.cpp
@@ -1882,3 +1882,77 @@ void CppToolsPlugin::test_completion_QTCREATORBUG9098()
     QVERIFY(completions.contains(QLatin1String("c")));
     QVERIFY(completions.contains(QLatin1String("B")));
 }
+
+void CppToolsPlugin::test_completion_typedef_of_templated_typedef_QTCREATORBUG8375()
+{
+    TestData data;
+    data.srcText =
+            "struct Foo\n"
+            "{ void bar(); };\n"
+            "struct A\n"
+            "{ typedef Foo AFoo; };\n"
+            "template <class T>\n"
+            "struct B\n"
+            "{ typedef typename T::AFoo BFoo; };\n"
+            "struct C : public B<A>\n"
+            "{\n"
+            "    void test()\n"
+            "    {\n"
+            "        BFoo foo;\n"
+            "        @\n"
+            "        // padding so we get the scope right\n"
+            "    }\n"
+            "};\n"
+            ;
+    setup(&data);
+
+    Utils::ChangeSet change;
+    QString txt = QLatin1String("foo.");
+    change.insert(data.pos, txt);
+    QTextCursor cursor(data.doc);
+    change.apply(&cursor);
+    data.pos += txt.length();
+
+    QStringList completions = getCompletions(data);
+
+    QCOMPARE(completions.size(), 2);
+    QVERIFY(completions.contains(QLatin1String("Foo")));
+    QVERIFY(completions.contains(QLatin1String("bar")));
+}
+
+void CppToolsPlugin::test_completion_typedef_with_the_same_base_name_and_new_type_name()
+{
+    TestData data;
+    data.srcText =
+            "namespace A\n"
+            "{\n"
+            "struct A { int aa; };\n"
+            "}\n"
+            "struct S\n"
+            "{\n"
+            "    typedef A::A A;\n"
+            "    A a;\n"
+            "};\n"
+            "void fun()\n"
+            "{\n"
+            "    S s;\n"
+            "   @\n"
+            "   // padding so we get the scope right\n"
+            "};\n"
+            ;
+    setup(&data);
+
+    Utils::ChangeSet change;
+    QString txt = QLatin1String("s.a.");
+    change.insert(data.pos, txt);
+    QTextCursor cursor(data.doc);
+    change.apply(&cursor);
+    data.pos += txt.length();
+
+    QStringList completions = getCompletions(data);
+
+    QCOMPARE(completions.size(), 2);
+    QVERIFY(completions.contains(QLatin1String("A")));
+    QVERIFY(completions.contains(QLatin1String("aa")));
+}
+
diff --git a/src/plugins/cpptools/cpptoolsplugin.h b/src/plugins/cpptools/cpptoolsplugin.h
index 10975a53013d09e1f02aed4de8a230a5041c2670..3bfb64688be07da66b8081259e612802eeeb84df 100644
--- a/src/plugins/cpptools/cpptoolsplugin.h
+++ b/src/plugins/cpptools/cpptoolsplugin.h
@@ -124,6 +124,8 @@ private slots:
     void test_completion_typedef_using_templates2();
     void test_completion_namespace_alias_with_many_namespace_declarations();
     void test_completion_QTCREATORBUG9098();
+    void test_completion_typedef_of_templated_typedef_QTCREATORBUG8375();
+    void test_completion_typedef_with_the_same_base_name_and_new_type_name();
 
     void test_format_pointerdeclaration_in_simpledeclarations();
     void test_format_pointerdeclaration_in_simpledeclarations_data();