diff --git a/src/libs/cplusplus/CheckUndefinedSymbols.cpp b/src/libs/cplusplus/CheckUndefinedSymbols.cpp
index 7b1d0a8f79c8ee55dfb403890c0901ddb5b14cfc..245b6be21eaddacd7a2037164f76a56645a8f035 100644
--- a/src/libs/cplusplus/CheckUndefinedSymbols.cpp
+++ b/src/libs/cplusplus/CheckUndefinedSymbols.cpp
@@ -137,6 +137,12 @@ protected:
 
     virtual bool visit(Function *symbol)
     {
+        for (TemplateParameters *p = symbol->templateParameters(); p; p = p->previous()) {
+            Scope *scope = p->scope();
+            for (unsigned i = 0; i < scope->symbolCount(); ++i)
+                accept(scope->symbolAt(i));
+        }
+
         addScope(symbol);
         return true;
     }
@@ -183,6 +189,12 @@ protected:
 
     virtual bool visit(Class *symbol)
     {
+        for (TemplateParameters *p = symbol->templateParameters(); p; p = p->previous()) {
+            Scope *scope = p->scope();
+            for (unsigned i = 0; i < scope->symbolCount(); ++i)
+                accept(scope->symbolAt(i));
+        }
+
         addScope(symbol);
         addType(symbol->name());
         return true;
@@ -190,6 +202,12 @@ protected:
 
     virtual bool visit(ForwardClassDeclaration *symbol)
     {
+        for (TemplateParameters *p = symbol->templateParameters(); p; p = p->previous()) {
+            Scope *scope = p->scope();
+            for (unsigned i = 0; i < scope->symbolCount(); ++i)
+                accept(scope->symbolAt(i));
+        }
+
         addType(symbol->name());
         return true;
     }
@@ -326,16 +344,13 @@ void CheckUndefinedSymbols::checkNamespace(NameAST *name)
 void CheckUndefinedSymbols::checkName(NameAST *ast)
 {
     if (ast->name) {
-        const QByteArray id = QByteArray::fromRawData(ast->name->identifier()->chars(), // ### move
-                                                      ast->name->identifier()->size());
-        if (_potentialTypes.contains(id)) {
-            const unsigned tokenOffset = tokenAt(ast->firstToken()).offset;
-            Scope *scope = CollectTypes::findScope(tokenOffset, _scopes); // ### move
-            if (! scope)
-                scope = _context.thisDocument()->globalSymbols();
-
-            const QList<Symbol *> candidates = _context.lookup(ast->name, scope);
-            addTypeUsage(candidates, ast);
+        if (const Identifier *ident = ast->name->identifier()) {
+            const QByteArray id = QByteArray::fromRawData(ident->chars(), ident->size());
+            if (_potentialTypes.contains(id)) {
+                Scope *scope = findScope(ast);
+                const QList<Symbol *> candidates = _context.lookup(ast->name, scope);
+                addTypeUsage(candidates, ast);
+            }
         }
     }
 }
@@ -354,34 +369,24 @@ bool CheckUndefinedSymbols::visit(TemplateIdAST *ast)
 
 bool CheckUndefinedSymbols::visit(DestructorNameAST *ast)
 {
-    if (ast->name) {
-        const QByteArray id = QByteArray::fromRawData(ast->name->identifier()->chars(), // ### move
-                                                      ast->name->identifier()->size());
-        if (_potentialTypes.contains(id)) {
-            Scope *scope = CollectTypes::findScope(tokenAt(ast->firstToken()).offset, _scopes); // ### move
-            if (! scope)
-                scope = _context.thisDocument()->globalSymbols();
-
-            ClassOrNamespace *b = _context.lookupType(ast->name, scope);
-            addTypeUsage(b, ast);
-        }
-    }
-
+    checkName(ast);
     return true;
 }
 
 bool CheckUndefinedSymbols::visit(QualifiedNameAST *ast)
 {
     if (ast->name) {
-        Scope *scope = CollectTypes::findScope(tokenAt(ast->firstToken()).offset, _scopes); // ### move
-        if (! scope)
-            scope = _context.thisDocument()->globalSymbols();
+        Scope *scope = findScope(ast);
 
         ClassOrNamespace *b = 0;
         if (NestedNameSpecifierListAST *it = ast->nested_name_specifier_list) {
             NestedNameSpecifierAST *nested_name_specifier = it->value;
             NameAST *class_or_namespace_name = nested_name_specifier->class_or_namespace_name; // ### remove shadowing
 
+            if (class_or_namespace_name)
+                if (TemplateIdAST *template_id = class_or_namespace_name->asTemplateId())
+                    accept(template_id->template_argument_list);
+
             const Name *name = class_or_namespace_name->name;
             b = _context.lookupType(name, scope);
             addTypeUsage(b, class_or_namespace_name);
@@ -390,6 +395,9 @@ bool CheckUndefinedSymbols::visit(QualifiedNameAST *ast)
                 NestedNameSpecifierAST *nested_name_specifier = it->value;
 
                 if (NameAST *class_or_namespace_name = nested_name_specifier->class_or_namespace_name) {
+                    if (TemplateIdAST *template_id = class_or_namespace_name->asTemplateId())
+                        accept(template_id->template_argument_list);
+
                     b = b->findType(class_or_namespace_name->name);
                     addTypeUsage(b, class_or_namespace_name);
                 }
@@ -403,17 +411,53 @@ bool CheckUndefinedSymbols::visit(QualifiedNameAST *ast)
     return false;
 }
 
+bool CheckUndefinedSymbols::visit(TypenameTypeParameterAST *ast)
+{
+    if (ast->name) {
+        if (const Identifier *templId = ast->name->name->identifier()) {
+            const QByteArray id = QByteArray::fromRawData(templId->chars(), templId->size());
+            if (_potentialTypes.contains(id)) {
+                Scope *scope = findScope(_templateDeclarationStack.back());
+                const QList<Symbol *> candidates = _context.lookup(ast->name->name, scope);
+                addTypeUsage(candidates, ast->name);
+            }
+        }
+    }
+    return true;
+}
+
+bool CheckUndefinedSymbols::visit(TemplateTypeParameterAST *ast)
+{
+    checkName(ast->name);
+    return true;
+}
+
+bool CheckUndefinedSymbols::visit(TemplateDeclarationAST *ast)
+{
+    _templateDeclarationStack.append(ast);
+    return true;
+}
+
+void CheckUndefinedSymbols::endVisit(TemplateDeclarationAST *)
+{
+    _templateDeclarationStack.takeFirst();
+}
+
 void CheckUndefinedSymbols::addTypeUsage(ClassOrNamespace *b, NameAST *ast)
 {
     if (! b)
         return;
 
-    const Token &tok = tokenAt(ast->firstToken());
+    unsigned startToken = ast->firstToken();
+    if (DestructorNameAST *dtor = ast->asDestructorName())
+        startToken = dtor->identifier_token;
+
+    const Token &tok = tokenAt(startToken);
     if (tok.generated())
         return;
 
     unsigned line, column;
-    getTokenStartPosition(ast->firstToken(), &line, &column);
+    getTokenStartPosition(startToken, &line, &column);
     const unsigned length = tok.length();
     Use use(line, column, length);
     _typeUsages.append(use);
@@ -422,12 +466,16 @@ void CheckUndefinedSymbols::addTypeUsage(ClassOrNamespace *b, NameAST *ast)
 
 void CheckUndefinedSymbols::addTypeUsage(const QList<Symbol *> &candidates, NameAST *ast)
 {
-    const Token &tok = tokenAt(ast->firstToken());
+    unsigned startToken = ast->firstToken();
+    if (DestructorNameAST *dtor = ast->asDestructorName())
+        startToken = dtor->identifier_token;
+
+    const Token &tok = tokenAt(startToken);
     if (tok.generated())
         return;
 
     unsigned line, column;
-    getTokenStartPosition(ast->firstToken(), &line, &column);
+    getTokenStartPosition(startToken, &line, &column);
     const unsigned length = tok.length();
 
     foreach (Symbol *c, candidates) {
@@ -450,3 +498,34 @@ QList<CheckUndefinedSymbols::Use> CheckUndefinedSymbols::typeUsages() const
 {
     return _typeUsages;
 }
+
+unsigned CheckUndefinedSymbols::startOfTemplateDeclaration(TemplateDeclarationAST *ast) const
+{
+    if (ast->declaration) {
+        if (TemplateDeclarationAST *templ = ast->declaration->asTemplateDeclaration())
+            return startOfTemplateDeclaration(templ);
+
+        return ast->declaration->firstToken();
+    }
+
+    return ast->firstToken();
+}
+
+Scope *CheckUndefinedSymbols::findScope(AST *ast) const
+{
+    Scope *scope = 0;
+
+    if (ast) {
+        unsigned startToken = ast->firstToken();
+        if (TemplateDeclarationAST *templ = ast->asTemplateDeclaration())
+            startToken = startOfTemplateDeclaration(templ);
+
+        const unsigned tokenOffset = tokenAt(startToken).offset;
+        scope = CollectTypes::findScope(tokenOffset, _scopes);
+    }
+
+    if (! scope)
+        scope = _context.thisDocument()->globalSymbols();
+
+    return scope;
+}
diff --git a/src/libs/cplusplus/CheckUndefinedSymbols.h b/src/libs/cplusplus/CheckUndefinedSymbols.h
index 0ca9f5184e1af9cc72442ac7959a255797a94bbf..fd5ffbc78610a1804fe2f77d5869d845f78ef88b 100644
--- a/src/libs/cplusplus/CheckUndefinedSymbols.h
+++ b/src/libs/cplusplus/CheckUndefinedSymbols.h
@@ -58,6 +58,7 @@ public:
 
 protected:
     using ASTVisitor::visit;
+    using ASTVisitor::endVisit;
 
     bool warning(unsigned line, unsigned column, const QString &text, unsigned length = 0);
     bool warning(AST *ast, const QString &text);
@@ -77,6 +78,15 @@ protected:
     virtual bool visit(QualifiedNameAST *ast);
     virtual bool visit(TemplateIdAST *ast);
 
+    virtual bool visit(TemplateDeclarationAST *ast);
+    virtual void endVisit(TemplateDeclarationAST *ast);
+
+    virtual bool visit(TypenameTypeParameterAST *ast);
+    virtual bool visit(TemplateTypeParameterAST *ast);
+
+    unsigned startOfTemplateDeclaration(TemplateDeclarationAST *ast) const;
+    Scope *findScope(AST *ast) const;
+
 private:
     LookupContext _context;
     QString _fileName;
@@ -84,6 +94,7 @@ private:
     QSet<QByteArray> _potentialTypes;
     QList<ScopedSymbol *> _scopes;
     QList<Use> _typeUsages;
+    QList<TemplateDeclarationAST *> _templateDeclarationStack;
 };
 
 } // end of namespace CPlusPlus
diff --git a/src/libs/cplusplus/FindUsages.cpp b/src/libs/cplusplus/FindUsages.cpp
index 795de07f9357fbf9f5f4070b061cb3f7c4ff7ba5..190168f919c63734932616a310d1e63987af8b02 100644
--- a/src/libs/cplusplus/FindUsages.cpp
+++ b/src/libs/cplusplus/FindUsages.cpp
@@ -28,6 +28,7 @@
 **************************************************************************/
 
 #include "FindUsages.h"
+#include "Overview.h"
 
 #include <Control.h>
 #include <Literals.h>
@@ -436,3 +437,54 @@ bool FindUsages::visit(QtPropertyDeclarationAST *)
 
 void FindUsages::endVisit(QtPropertyDeclarationAST *)
 { _inQProperty = false; }
+
+bool FindUsages::visit(TemplateDeclarationAST *ast)
+{
+    _templateDeclarationStack.append(ast);
+    return true;
+}
+
+void FindUsages::endVisit(TemplateDeclarationAST *)
+{
+    _templateDeclarationStack.takeFirst();
+}
+
+bool FindUsages::visit(TypenameTypeParameterAST *ast)
+{
+    if (NameAST *name = ast->name) {
+        const Identifier *id = name->name->identifier();
+        if (id == _id) {
+            unsigned start = startOfTemplateDeclaration(_templateDeclarationStack.back());
+            const QList<Symbol *> candidates = _context.lookup(name->name, scopeAt(start));
+            reportResult(ast->name->firstToken(), candidates);
+        }
+    }
+    accept(ast->type_id);
+    return false;
+}
+
+bool FindUsages::visit(TemplateTypeParameterAST *ast)
+{
+    if (NameAST *name = ast->name) {
+        const Identifier *id = name->name->identifier();
+        if (id == _id) {
+            unsigned start = startOfTemplateDeclaration(_templateDeclarationStack.back());
+            const QList<Symbol *> candidates = _context.lookup(name->name, scopeAt(start));
+            reportResult(ast->name->firstToken(), candidates);
+        }
+    }
+    accept(ast->type_id);
+    return false;
+}
+
+unsigned FindUsages::startOfTemplateDeclaration(TemplateDeclarationAST *ast) const
+{
+    if (ast->declaration) {
+        if (TemplateDeclarationAST *templ = ast->declaration->asTemplateDeclaration())
+            return startOfTemplateDeclaration(templ);
+
+        return ast->declaration->firstToken();
+    }
+
+    return ast->firstToken();
+}
diff --git a/src/libs/cplusplus/FindUsages.h b/src/libs/cplusplus/FindUsages.h
index 1bcaa66609b5f2319f6597b30d30328f1ca8dcef..d2809db995a259fc9cfd4e726c2aba4b9dcb3963 100644
--- a/src/libs/cplusplus/FindUsages.h
+++ b/src/libs/cplusplus/FindUsages.h
@@ -99,6 +99,14 @@ protected:
     virtual bool visit(QtPropertyDeclarationAST *);
     virtual void endVisit(QtPropertyDeclarationAST *);
 
+    virtual bool visit(TemplateDeclarationAST *ast);
+    virtual void endVisit(TemplateDeclarationAST *ast);
+
+    virtual bool visit(TypenameTypeParameterAST *ast);
+    virtual bool visit(TemplateTypeParameterAST *ast);
+
+    unsigned startOfTemplateDeclaration(TemplateDeclarationAST *ast) const;
+
 private:
     const Identifier *_id;
     Symbol *_declSymbol;
@@ -110,6 +118,7 @@ private:
     Semantic _sem;
     QList<PostfixExpressionAST *> _postfixExpressionStack;
     QList<QualifiedNameAST *> _qualifiedNameStack;
+    QList<TemplateDeclarationAST *> _templateDeclarationStack;
     QList<int> _references;
     QList<Usage> _usages;
     int _inSimpleDeclaration;