diff --git a/src/libs/3rdparty/cplusplus/Name.cpp b/src/libs/3rdparty/cplusplus/Name.cpp
index 6c1240b279ed3ae6ed7bbff8ae79a916092ecdec..8fec45f5c07c01ed90302883541297bc52305fbe 100644
--- a/src/libs/3rdparty/cplusplus/Name.cpp
+++ b/src/libs/3rdparty/cplusplus/Name.cpp
@@ -18,10 +18,13 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
+#include "Literals.h"
 #include "Name.h"
 #include "Names.h"
 #include "NameVisitor.h"
 
+#include <cstring>
+
 using namespace CPlusPlus;
 
 Name::Name()
@@ -65,4 +68,16 @@ void Name::accept(const Name *name, NameVisitor *visitor)
     name->accept(visitor);
 }
 
+bool Name::Compare::operator()(const Name *name, const Name *other) const
+{
+    if (name == 0)
+        return other != 0;
+    if (other == 0)
+        return false;
+    if (name == other)
+        return false;
 
+    const Identifier *id = name->identifier();
+    const Identifier *otherId = other->identifier();
+    return std::strcmp(id->chars(), otherId->chars()) < 0;
+}
diff --git a/src/libs/3rdparty/cplusplus/Name.h b/src/libs/3rdparty/cplusplus/Name.h
index 8a34b364790b6ae397785df1df4c95e6757ae6e2..43dcf3d35cc146f39bc02fe066a751ab4693a51e 100644
--- a/src/libs/3rdparty/cplusplus/Name.h
+++ b/src/libs/3rdparty/cplusplus/Name.h
@@ -23,6 +23,7 @@
 
 #include "CPlusPlusForwardDeclarations.h"
 
+#include <functional>
 
 namespace CPlusPlus {
 
@@ -55,6 +56,11 @@ public:
     void accept(NameVisitor *visitor) const;
     static void accept(const Name *name, NameVisitor *visitor);
 
+public:
+    struct Compare: std::binary_function<const Name *, const Name *, bool> {
+        bool operator()(const Name *name, const Name *other) const;
+    };
+
 protected:
     virtual void accept0(NameVisitor *visitor) const = 0;
 };
diff --git a/src/libs/3rdparty/cplusplus/Templates.cpp b/src/libs/3rdparty/cplusplus/Templates.cpp
index 095fa010a93c8d14c7e1fb20e0e1c5a3ebda4d17..1c4ec61ced5395e3964f60b6165d0a9aa1695b58 100644
--- a/src/libs/3rdparty/cplusplus/Templates.cpp
+++ b/src/libs/3rdparty/cplusplus/Templates.cpp
@@ -514,6 +514,8 @@ Symbol *Clone::instantiate(Template *templ, const FullySpecifiedType *const args
 //
 // substitutions
 //
+
+
 FullySpecifiedType Subst::apply(const Name *name) const
 {
     if (name) {
diff --git a/src/libs/3rdparty/cplusplus/Templates.h b/src/libs/3rdparty/cplusplus/Templates.h
index 0057d7fcbfc13610af8de993978c026506ca4dc1..04064a8906732d4af65a111ed4ea62e1721fdceb 100644
--- a/src/libs/3rdparty/cplusplus/Templates.h
+++ b/src/libs/3rdparty/cplusplus/Templates.h
@@ -24,6 +24,7 @@
 #include "CPlusPlusForwardDeclarations.h"
 #include "TypeVisitor.h"
 #include "FullySpecifiedType.h"
+#include "Name.h"
 #include "NameVisitor.h"
 #include "SymbolVisitor.h"
 #include <map>
@@ -56,7 +57,7 @@ public:
 private:
     Control *_control;
     Subst *_previous;
-    std::map<const Name *, FullySpecifiedType> _map;
+    std::map<const Name *, FullySpecifiedType, Name::Compare> _map;
 };
 
 class CPLUSPLUS_EXPORT CloneType: protected TypeVisitor
diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp
index 51efb92a29c7357a8c78a254cba6324e8ba35af5..1fbe5c5e601170b2ed187951d3aa917cf8ecd6e6 100644
--- a/src/libs/cplusplus/LookupContext.cpp
+++ b/src/libs/cplusplus/LookupContext.cpp
@@ -120,21 +120,12 @@ bool compareFullyQualifiedName(const QList<const Name *> &path, const QList<cons
 
 }
 
-bool ClassOrNamespace::CompareName::operator()(const Name *name, const Name *other) const
-{
-    Q_ASSERT(name != 0);
-    Q_ASSERT(other != 0);
-
-    const Identifier *id = name->identifier();
-    const Identifier *otherId = other->identifier();
-    return strcmp(id->chars(), otherId->chars()) < 0;
-}
-
 /////////////////////////////////////////////////////////////////////
 // LookupContext
 /////////////////////////////////////////////////////////////////////
 LookupContext::LookupContext()
     : _control(new Control())
+    , m_expandTemplates(false)
 { }
 
 LookupContext::LookupContext(Document::Ptr thisDocument,
@@ -142,7 +133,8 @@ LookupContext::LookupContext(Document::Ptr thisDocument,
     : _expressionDocument(Document::create("<LookupContext>")),
       _thisDocument(thisDocument),
       _snapshot(snapshot),
-      _control(new Control())
+      _control(new Control()),
+      m_expandTemplates(false)
 {
 }
 
@@ -152,7 +144,8 @@ LookupContext::LookupContext(Document::Ptr expressionDocument,
     : _expressionDocument(expressionDocument),
       _thisDocument(thisDocument),
       _snapshot(snapshot),
-      _control(new Control())
+      _control(new Control()),
+      m_expandTemplates(false)
 {
 }
 
@@ -161,7 +154,8 @@ LookupContext::LookupContext(const LookupContext &other)
       _thisDocument(other._thisDocument),
       _snapshot(other._snapshot),
       _bindings(other._bindings),
-      _control(other._control)
+      _control(other._control),
+      m_expandTemplates(other.m_expandTemplates)
 { }
 
 LookupContext &LookupContext::operator = (const LookupContext &other)
@@ -171,6 +165,7 @@ LookupContext &LookupContext::operator = (const LookupContext &other)
     _snapshot = other._snapshot;
     _bindings = other._bindings;
     _control = other._control;
+    m_expandTemplates = other.m_expandTemplates;
     return *this;
 }
 
@@ -227,8 +222,10 @@ const Name *LookupContext::minimalName(Symbol *symbol, ClassOrNamespace *target,
 
 QSharedPointer<CreateBindings> LookupContext::bindings() const
 {
-    if (! _bindings)
+    if (! _bindings) {
         _bindings = QSharedPointer<CreateBindings>(new CreateBindings(_thisDocument, _snapshot, control()));
+        _bindings->setExpandTemplates(m_expandTemplates);
+    }
 
     return _bindings;
 }
@@ -728,7 +725,6 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac
         instantiation->_instantiationOrigin = origin;
 
         // The instantiation should have all symbols, enums, and usings from the reference.
-        instantiation->_symbols.append(reference->symbols());
         instantiation->_enums.append(reference->enums());
         instantiation->_usings.append(reference->usings());
 
@@ -736,6 +732,28 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac
         // now must worry about dependent names in base classes.
         if (Template *templ = referenceClass->enclosingTemplate()) {
             const unsigned argumentCount = templId->templateArgumentCount();
+
+            if (_factory->expandTemplates()) {
+                Subst subst(_control.data());
+                for (unsigned i = 0, ei = std::min(argumentCount, templ->templateParameterCount()); i < ei; ++i) {
+                    const TypenameArgument *tParam = templ->templateParameterAt(i)->asTypenameArgument();
+                    if (!tParam)
+                        continue;
+                    const Name *name = tParam->name();
+                    if (!name)
+                        continue;
+                    const FullySpecifiedType &ty = templId->templateArgumentAt(i);
+                    subst.bind(name, ty);
+                }
+
+                Clone cloner(_control.data());
+                foreach (Symbol *s, reference->symbols()) {
+                    instantiation->_symbols.append(cloner.symbol(s, &subst));
+                }
+            } else {
+                instantiation->_symbols.append(reference->symbols());
+            }
+
             QHash<const Name*, unsigned> templParams;
             for (unsigned i = 0; i < templ->templateParameterCount(); ++i)
                 templParams.insert(templ->templateParameterAt(i)->name(), i);
@@ -794,6 +812,8 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac
                 if (baseBinding && !knownUsings.contains(baseBinding))
                     instantiation->addUsing(baseBinding);
             }
+        } else {
+            instantiation->_symbols.append(reference->symbols());
         }
 
         _alreadyConsideredTemplates.clear(templId);
@@ -907,7 +927,7 @@ ClassOrNamespace *ClassOrNamespace::findOrCreateType(const Name *name, ClassOrNa
 }
 
 CreateBindings::CreateBindings(Document::Ptr thisDocument, const Snapshot &snapshot, QSharedPointer<Control> control)
-    : _snapshot(snapshot), _control(control)
+    : _snapshot(snapshot), _control(control), _expandTemplates(false)
 {
     _globalNamespace = allocClassOrNamespace(/*parent = */ 0);
     _currentClassOrNamespace = _globalNamespace;
diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h
index 41b5ee9999a7003760fda3bc31dbe2d160ee6bd6..c7b556de432b2f74eef866930d0e408aa31a0e28 100644
--- a/src/libs/cplusplus/LookupContext.h
+++ b/src/libs/cplusplus/LookupContext.h
@@ -119,12 +119,7 @@ private:
     ClassOrNamespace *nestedType(const Name *name, ClassOrNamespace *origin);
 
 private:
-    struct CompareName: std::binary_function<const Name *, const Name *, bool> {
-        bool operator()(const Name *name, const Name *other) const;
-    };
-
-private:
-    typedef std::map<const Name *, ClassOrNamespace *, CompareName> Table;
+    typedef std::map<const Name *, ClassOrNamespace *, Name::Compare> Table;
     CreateBindings *_factory;
     ClassOrNamespace *_parent;
     QList<Symbol *> _symbols;
@@ -163,6 +158,11 @@ public:
     /// \internal
     QSharedPointer<Control> control() const;
 
+    bool expandTemplates() const
+    { return _expandTemplates; }
+    void setExpandTemplates(bool expandTemplates)
+    { _expandTemplates = expandTemplates; }
+
     /// Searches in \a scope for symbols with the given \a name.
     /// Store the result in \a results.
     /// \internal
@@ -223,6 +223,7 @@ private:
     QList<ClassOrNamespace *> _entities;
     ClassOrNamespace *_globalNamespace;
     ClassOrNamespace *_currentClassOrNamespace;
+    bool _expandTemplates;
 };
 
 class CPLUSPLUS_EXPORT LookupContext
@@ -265,6 +266,9 @@ public:
 
     static const Name *minimalName(Symbol *symbol, ClassOrNamespace *target, Control *control);
 
+    void setExpandTemplates(bool expandTemplates)
+    { m_expandTemplates = expandTemplates; }
+
 private:
     // The current expression.
     Document::Ptr _expressionDocument;
@@ -279,6 +283,8 @@ private:
     mutable QSharedPointer<CreateBindings> _bindings;
 
     QSharedPointer<Control> _control;
+
+    bool m_expandTemplates;
 };
 
 bool CPLUSPLUS_EXPORT compareName(const Name *name, const Name *other);
diff --git a/src/libs/cplusplus/TypeOfExpression.cpp b/src/libs/cplusplus/TypeOfExpression.cpp
index e8deecd5aeca47dad4a117ab161ee0e6b73cc14c..379388de214185db5b6a2c99578ba26e10972035 100644
--- a/src/libs/cplusplus/TypeOfExpression.cpp
+++ b/src/libs/cplusplus/TypeOfExpression.cpp
@@ -41,7 +41,8 @@ using namespace CPlusPlus;
 
 TypeOfExpression::TypeOfExpression():
     m_ast(0),
-    m_scope(0)
+    m_scope(0),
+    m_expandTemplates(false)
 {
 }
 
@@ -107,6 +108,7 @@ QList<LookupItem> TypeOfExpression::operator()(ExpressionAST *expression,
 
     m_lookupContext = LookupContext(document, m_thisDocument, m_snapshot);
     m_lookupContext.setBindings(m_bindings);
+    m_lookupContext.setExpandTemplates(m_expandTemplates);
 
     ResolveExpression resolve(m_lookupContext);
     const QList<LookupItem> items = resolve(m_ast, scope);
@@ -127,6 +129,7 @@ QList<LookupItem> TypeOfExpression::reference(ExpressionAST *expression,
 
     m_lookupContext = LookupContext(document, m_thisDocument, m_snapshot);
     m_lookupContext.setBindings(m_bindings);
+    m_lookupContext.setExpandTemplates(m_expandTemplates);
 
     ResolveExpression resolve(m_lookupContext);
     const QList<LookupItem> items = resolve.reference(m_ast, scope);
diff --git a/src/libs/cplusplus/TypeOfExpression.h b/src/libs/cplusplus/TypeOfExpression.h
index fb425db08b63f18dc5541072a705bd9af9f1a909..d0cf07da9895ed00336b002c088443ffa58b3fb1 100644
--- a/src/libs/cplusplus/TypeOfExpression.h
+++ b/src/libs/cplusplus/TypeOfExpression.h
@@ -123,6 +123,9 @@ public:
     ExpressionAST *expressionAST() const;
     QByteArray preprocessedExpression(const QByteArray &utf8code) const;
 
+    void setExpandTemplates(bool expandTemplates)
+    { m_expandTemplates = expandTemplates; }
+
 private:
 
     void processEnvironment(Document::Ptr doc, Environment *env,
@@ -137,6 +140,8 @@ private:
     Scope *m_scope;
     LookupContext m_lookupContext;
     mutable QSharedPointer<Environment> m_environment;
+
+    bool m_expandTemplates;
 };
 
 ExpressionAST CPLUSPLUS_EXPORT *extractExpressionAST(Document::Ptr doc);
diff --git a/src/plugins/cpptools/cppcompletion_test.cpp b/src/plugins/cpptools/cppcompletion_test.cpp
index 559788e4d6bc12adb196d48455f5700ee5e89d24..72438d114bb170eb1cfe6b437b3f2f6f15fc5bd4 100644
--- a/src/plugins/cpptools/cppcompletion_test.cpp
+++ b/src/plugins/cpptools/cppcompletion_test.cpp
@@ -228,6 +228,78 @@ void CppToolsPlugin::test_completion_template_1()
     QVERIFY(!completions.contains("func"));
 }
 
+void CppToolsPlugin::test_completion_template_2()
+{
+    TestData data;
+    data.srcText = "\n"
+            "template <class T>\n"
+            "struct List\n"
+            "{\n"
+            "    T &at(int);\n"
+            "};\n"
+            "\n"
+            "struct Tupple { int a; int b; };\n"
+            "\n"
+            "void func() {\n"
+            "    List<Tupple> l;\n"
+            "    @\n"
+            "    // padding so we get the scope right\n"
+            "}";
+
+    setup(&data);
+
+    Utils::ChangeSet change;
+    QString txt = QLatin1String("l.at(0).");
+    change.insert(data.pos, txt);
+    QTextCursor cursor(data.doc);
+    change.apply(&cursor);
+    data.pos += txt.length();
+
+    QStringList completions = getCompletions(data);
+
+    QCOMPARE(completions.size(), 3);
+    QVERIFY(completions.contains("Tupple"));
+    QVERIFY(completions.contains("a"));
+    QVERIFY(completions.contains("b"));
+}
+
+void CppToolsPlugin::test_completion_template_3()
+{
+    TestData data;
+    data.srcText = "\n"
+            "template <class T>\n"
+            "struct List\n"
+            "{\n"
+            "    T t;\n"
+            "};\n"
+            "\n"
+            "struct Tupple { int a; int b; };\n"
+            "\n"
+            "void func() {\n"
+            "    List<Tupple> l;\n"
+            "    @\n"
+            "    // padding so we get the scope right\n"
+            "}";
+
+    setup(&data);
+
+    Utils::ChangeSet change;
+    QString txt = QLatin1String("l.t.");
+    change.insert(data.pos, txt);
+    QTextCursor cursor(data.doc);
+    change.apply(&cursor);
+    data.pos += txt.length();
+
+    QStringList completions = getCompletions(data);
+
+    QCOMPARE(completions.size(), 3);
+    QVERIFY(completions.contains("Tupple"));
+    QVERIFY(completions.contains("a"));
+    QVERIFY(completions.contains("b"));
+    QVERIFY(completions.contains("a"));
+    QVERIFY(completions.contains("b"));
+}
+
 void CppToolsPlugin::test_completion()
 {
     QFETCH(QByteArray, code);
diff --git a/src/plugins/cpptools/cppcompletionassist.cpp b/src/plugins/cpptools/cppcompletionassist.cpp
index 2428b7c32b8509fc721b8733b43a177e55f86aaf..8dd911aac858a697e697eb3392fc778110b375b5 100644
--- a/src/plugins/cpptools/cppcompletionassist.cpp
+++ b/src/plugins/cpptools/cppcompletionassist.cpp
@@ -102,7 +102,9 @@ public:
         , m_completionOperator(T_EOF_SYMBOL)
         , m_replaceDotForArrow(false)
         , m_typeOfExpression(new TypeOfExpression)
-    {}
+    {
+        m_typeOfExpression->setExpandTemplates(true);
+    }
 
     virtual bool isSortable(const QString &prefix) const;
     virtual IAssistProposalItem *proposalItem(int index) const;
diff --git a/src/plugins/cpptools/cpptoolsplugin.h b/src/plugins/cpptools/cpptoolsplugin.h
index 80b05ba63f11db45a3d0126e3ce89015d60af25b..6bc1ddef44a9339b3bbb2fc8627282db28879ae2 100644
--- a/src/plugins/cpptools/cpptoolsplugin.h
+++ b/src/plugins/cpptools/cpptoolsplugin.h
@@ -93,6 +93,8 @@ private slots:
     void test_completion_forward_declarations_present();
     void test_completion_basic_1();
     void test_completion_template_1();
+    void test_completion_template_2();
+    void test_completion_template_3();
     void test_completion_template_as_base();
     void test_completion_template_as_base_data();
     void test_completion_use_global_identifier_as_base_class();