diff --git a/src/libs/cplusplus/Icons.cpp b/src/libs/cplusplus/Icons.cpp
index 8626088052f1cc946600fe327545145a2cc21ff8..5071efde8ab89ea524549645204e6f61787ea7a5 100644
--- a/src/libs/cplusplus/Icons.cpp
+++ b/src/libs/cplusplus/Icons.cpp
@@ -100,7 +100,7 @@ QIcon Icons::iconForSymbol(const Symbol *symbol) const
         }
     } else if (symbol->isEnum()) {
         return _enumIcon;
-    } else if (symbol->isClass()) {
+    } else if (symbol->isClass() || symbol->isForwardClassDeclaration()) {
         return _classIcon;
     } else if (symbol->isNamespace()) {
         return _namespaceIcon;
diff --git a/src/libs/cplusplus/Overview.cpp b/src/libs/cplusplus/Overview.cpp
index 0f973753d0b29326d52c866eea639f1e28c3cea1..331471fe3638652f7f9826ff6c9d6d8bd67a19f2 100644
--- a/src/libs/cplusplus/Overview.cpp
+++ b/src/libs/cplusplus/Overview.cpp
@@ -42,7 +42,8 @@ Overview::Overview()
     : _markArgument(0),
       _showArgumentNames(false),
       _showReturnTypes(false),
-      _showFunctionSignatures(true)
+      _showFunctionSignatures(true),
+      _showFullyQualifiedNames(false)
 { }
 
 Overview::~Overview()
@@ -88,6 +89,16 @@ void Overview::setShowFunctionSignatures(bool showFunctionSignatures)
     _showFunctionSignatures = showFunctionSignatures;
 }
 
+bool Overview::showFullyQualifiedNames() const
+{
+    return _showFullyQualifiedNames;
+}
+
+void Overview::setShowFullyQualifiedNamed(bool showFullyQualifiedNames)
+{
+    _showFullyQualifiedNames = showFullyQualifiedNames;
+}
+
 QString Overview::prettyName(Name *name) const
 {
     NamePrettyPrinter pp(this);
diff --git a/src/libs/cplusplus/Overview.h b/src/libs/cplusplus/Overview.h
index 6918ee45ff86539b1462b14df89bc2ba2c249ad8..f7076559f2a93fa94a4010e0e53fe2ae0e32fe20 100644
--- a/src/libs/cplusplus/Overview.h
+++ b/src/libs/cplusplus/Overview.h
@@ -57,6 +57,9 @@ public:
     bool showFunctionSignatures() const;
     void setShowFunctionSignatures(bool showFunctionSignatures);
 
+    bool showFullyQualifiedNames() const;
+    void setShowFullyQualifiedNamed(bool showFullyQualifiedNames);
+
     // 1-based
     // ### rename
     unsigned markArgument() const;
@@ -77,6 +80,7 @@ private:
     bool _showArgumentNames: 1;
     bool _showReturnTypes: 1;
     bool _showFunctionSignatures: 1;
+    bool _showFullyQualifiedNames: 1;
 };
 
 } // end of namespace CPlusPlus
diff --git a/src/libs/cplusplus/TypePrettyPrinter.cpp b/src/libs/cplusplus/TypePrettyPrinter.cpp
index 6e46361b7f42a15a1f77ba4fc7e6eea32fcf6f9a..a198844499c6ac820762b7b62871d584dc87508d 100644
--- a/src/libs/cplusplus/TypePrettyPrinter.cpp
+++ b/src/libs/cplusplus/TypePrettyPrinter.cpp
@@ -37,9 +37,41 @@
 #include <CoreTypes.h>
 #include <Symbols.h>
 #include <Scope.h>
+#include <QStringList>
+#include <QtDebug>
 
 using namespace CPlusPlus;
 
+
+static QString fullyQualifiedName(Symbol *symbol, const Overview *overview)
+{
+    QStringList nestedNameSpecifier;
+
+    for (Scope *scope = symbol->scope(); scope && scope->enclosingScope();
+         scope = scope->enclosingScope())
+    {
+        Symbol *owner = scope->owner();
+
+        if (! owner) {
+            qWarning() << "invalid scope."; // ### better message.
+            continue;
+        }
+
+        if (! owner->name())
+            nestedNameSpecifier.prepend(QLatin1String("<anonymous>"));
+
+        else {
+            const QString name = overview->prettyName(owner->name());
+
+            nestedNameSpecifier.prepend(name);
+        }
+    }
+
+    nestedNameSpecifier.append(overview->prettyName(symbol->name()));
+
+    return nestedNameSpecifier.join(QLatin1String("::"));
+}
+
 TypePrettyPrinter::TypePrettyPrinter(const Overview *overview)
     : _overview(overview),
       _name(0)
@@ -150,16 +182,26 @@ void TypePrettyPrinter::visit(Namespace *type)
     applyPtrOperators();
 }
 
-void TypePrettyPrinter::visit(Class *type)
+void TypePrettyPrinter::visit(Class *classTy)
 {
-    _text += overview()->prettyName(type->name());
+    if (overview()->showFullyQualifiedNames())
+        _text += fullyQualifiedName(classTy, overview());
+
+    else
+        _text += overview()->prettyName(classTy->name());
+
     applyPtrOperators();
 }
 
 
 void TypePrettyPrinter::visit(Enum *type)
 {
-    _text += overview()->prettyName(type->name());
+    if (overview()->showFullyQualifiedNames())
+        _text += fullyQualifiedName(type, overview());
+
+    else
+        _text += overview()->prettyName(type->name());
+
     applyPtrOperators();
 }
 
@@ -259,11 +301,14 @@ void TypePrettyPrinter::visit(Function *type)
     if (! _ptrOperators.isEmpty()) {
         out(QLatin1Char('('));
         applyPtrOperators(false);
+
         if (! _name.isEmpty()) {
             _text += _name;
             _name.clear();
         }
+
         out(QLatin1Char(')'));
+
     } else if (! _name.isEmpty() && _overview->showFunctionSignatures()) {
         space();
         out(_name);
diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp
index e47fbe658127ab192ef824b1a122007014741627..66dc226e4d7efd0bc33982a8c49f77f1a98db62d 100644
--- a/src/plugins/cppeditor/cpphoverhandler.cpp
+++ b/src/plugins/cppeditor/cpphoverhandler.cpp
@@ -47,6 +47,7 @@
 #include <CoreTypes.h>
 #include <FullySpecifiedType.h>
 #include <Literals.h>
+#include <Control.h>
 #include <Names.h>
 #include <Scope.h>
 #include <Symbol.h>
@@ -141,30 +142,13 @@ void CppHoverHandler::showToolTip(TextEditor::ITextEditor *editor, const QPoint
     }
 }
 
-static QString buildHelpId(const FullySpecifiedType &type,
-                           const Symbol *symbol)
+static QString buildHelpId(Symbol *symbol, Name *name)
 {
-    Name *name = 0;
     Scope *scope = 0;
 
-    if (const Function *f = type->asFunctionType()) {
-        name = f->name();
-        scope = f->scope();
-    } else if (const Class *c = type->asClassType()) {
-        name = c->name();
-        scope = c->scope();
-    } else if (const Enum *e = type->asEnumType()) {
-        name = e->name();
-        scope = e->scope();
-    } else if (const NamedType *t = type->asNamedType()) {
-        name = t->name();
-    } else if (symbol && symbol->isDeclaration()) {
-        const Declaration *d = symbol->asDeclaration();
-
-        if (d->scope() && d->scope()->isEnumScope()) {
-            name = d->name();
-            scope = d->scope();
-        }
+    if (symbol) {
+        scope = symbol->scope();
+        name = symbol->name();
     }
 
     if (! name)
@@ -178,14 +162,18 @@ static QString buildHelpId(const FullySpecifiedType &type,
     qualifiedNames.prepend(overview.prettyName(name));
 
     for (; scope; scope = scope->enclosingScope()) {
-        if (scope->owner() && scope->owner()->name() && !scope->isEnumScope()) {
-            Name *name = scope->owner()->name();
+        Symbol *owner = scope->owner();
+
+        if (owner && owner->name() && ! scope->isEnumScope()) {
+            Name *name = owner->name();
             Identifier *id = 0;
-            if (NameId *nameId = name->asNameId()) {
+
+            if (NameId *nameId = name->asNameId())
                 id = nameId->identifier();
-            } else if (TemplateNameId *nameId = name->asTemplateNameId()) {
+
+            else if (TemplateNameId *nameId = name->asTemplateNameId())
                 id = nameId->identifier();
-            }
+
             if (id)
                 qualifiedNames.prepend(QString::fromLatin1(id->chars(), id->size()));
         }
@@ -194,6 +182,70 @@ static QString buildHelpId(const FullySpecifiedType &type,
     return qualifiedNames.join(QLatin1String("::"));
 }
 
+// ### move me
+static FullySpecifiedType resolve(const FullySpecifiedType &ty,
+                                  const LookupContext &context,
+                                  Symbol **resolvedSymbol,
+                                  Name **resolvedName)
+{
+    Control *control = context.control();
+
+    if (const PointerType *ptrTy = ty->asPointerType()) {
+        return control->pointerType(resolve(ptrTy->elementType(), context,
+                                            resolvedSymbol, resolvedName));
+
+    } else if (const ReferenceType *refTy = ty->asReferenceType()) {
+        return control->referenceType(resolve(refTy->elementType(), context,
+                                              resolvedSymbol, resolvedName));
+
+    } else if (const PointerToMemberType *ptrToMemTy = ty->asPointerToMemberType()) {
+        return control->pointerToMemberType(ptrToMemTy->memberName(),
+                                            resolve(ptrToMemTy->elementType(), context,
+                                                    resolvedSymbol, resolvedName));
+
+    } else if (const NamedType *namedTy = ty->asNamedType()) {
+        if (resolvedName)
+            *resolvedName = namedTy->name();
+
+        const QList<Symbol *> candidates = context.resolve(namedTy->name());
+
+        foreach (Symbol *c, candidates) {
+            if (c->isClass() || c->isEnum()) {
+                if (resolvedSymbol)
+                    *resolvedSymbol = c;
+
+                return c->type();
+            }
+        }
+
+    } else if (const Namespace *nsTy = ty->asNamespaceType()) {
+        if (resolvedName)
+            *resolvedName = nsTy->name();
+
+    } else if (const Class *classTy = ty->asClassType()) {
+        if (resolvedName)
+            *resolvedName = classTy->name();
+
+        if (resolvedSymbol)
+            *resolvedSymbol = const_cast<Class *>(classTy);
+
+    } else if (const ForwardClassDeclaration *fwdClassTy = ty->asForwardClassDeclarationType()) {
+        if (resolvedName)
+            *resolvedName = fwdClassTy->name();
+
+    } else if (const Enum *enumTy = ty->asEnumType()) {
+        if (resolvedName)
+            *resolvedName = enumTy->name();
+
+    } else if (const Function *funTy = ty->asFunctionType()) {
+        if (resolvedName)
+            *resolvedName = funTy->name();
+
+    }
+
+    return ty;
+}
+
 void CppHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, int pos)
 {
     m_helpId.clear();
@@ -262,26 +314,38 @@ void CppHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, in
                 typeOfExpression(expression, doc, lastSymbol);
 
         if (!types.isEmpty()) {
-            FullySpecifiedType firstType = types.first().first;
-            Symbol *symbol = types.first().second;
-            FullySpecifiedType docType = firstType;
-
-            if (const PointerType *pt = firstType->asPointerType()) {
-                docType = pt->elementType();
-            } else if (const ReferenceType *rt = firstType->asReferenceType()) {
-                docType = rt->elementType();
-            }
+            const TypeOfExpression::Result result = types.first();
 
-            m_helpId = buildHelpId(docType, symbol);
-            QString displayName = buildHelpId(firstType, symbol);
+            FullySpecifiedType firstType = result.first; // result of `type of expression'.
+            Symbol *lookupSymbol = result.second;        // lookup symbol
 
-            if (!firstType->isClassType() && !firstType->isNamedType()) {
-                Overview overview;
-                overview.setShowArgumentNames(true);
-                overview.setShowReturnTypes(true);
-                m_toolTip = overview.prettyType(firstType, displayName);
-            } else {
+            Symbol *resolvedSymbol = 0;
+            Name *resolvedName = 0;
+            firstType = resolve(firstType, typeOfExpression.lookupContext(),
+                                &resolvedSymbol, &resolvedName);
+
+            m_helpId = buildHelpId(resolvedSymbol, resolvedName);
+
+            Symbol *symbol = result.second;
+            if (resolvedSymbol)
+                symbol = resolvedSymbol;
+
+            Overview overview;
+            overview.setShowArgumentNames(true);
+            overview.setShowReturnTypes(true);
+            overview.setShowFullyQualifiedNamed(true);
+
+            if (lookupSymbol && lookupSymbol->isDeclaration()) {
+                Declaration *decl = lookupSymbol->asDeclaration();
+                m_toolTip = overview.prettyType(firstType, decl->name());
+
+            } else if (firstType->isClassType() || firstType->isEnumType() ||
+                       firstType->isForwardClassDeclarationType()) {
                 m_toolTip = m_helpId;
+
+            } else {
+                m_toolTip = overview.prettyType(firstType, m_helpId);
+
             }
         }
     }
diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp
index 1d845a1e3e6dc8be5eaa63be933869e996869c77..6f41c83379d8380c6be61c28d4aee221566d348b 100644
--- a/src/plugins/debugger/gdbengine.cpp
+++ b/src/plugins/debugger/gdbengine.cpp
@@ -1562,6 +1562,7 @@ bool GdbEngine::startDebugger()
     //sendCommand("set pagination off");
     sendCommand("set breakpoint pending on", BreakEnablePending);
     sendCommand("set print elements 10000");
+    sendCommand("-data-list-register-names", RegisterListNames);
 
     // one of the following is needed to prevent crashes in gdb on code like:
     //  template <class T> T foo() { return T(0); }
@@ -1633,8 +1634,6 @@ bool GdbEngine::startDebugger()
         sendCommand("x/2i " + startSymbolName(), GdbStart);
     }
 
-    sendCommand("-data-list-register-names", RegisterListNames);
-
     // set all to "pending"
     if (q->startMode() == DebuggerManager::AttachExternal)
         qq->breakHandler()->removeAllBreakpoints();
diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp
index 8a9c201dc5d1be492b55da70e59f949fb0145df7..6ab5c9b92ec048f91e18340b753a05a083ffe101 100644
--- a/src/shared/cplusplus/AST.cpp
+++ b/src/shared/cplusplus/AST.cpp
@@ -1178,7 +1178,7 @@ unsigned DeclaratorListAST::lastToken() const
 {
     for (const DeclaratorListAST *it = this; it; it = it->next) {
         if (! it->next)
-            return it->lastToken();
+            return it->declarator->lastToken();
     }
     return 0;
 }
diff --git a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h
index 2909c0775ab2a90b3bd105214175c9acf664ae38..3233c7449f1b4c7059f81e876e4f463bf6f8db61 100644
--- a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h
+++ b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h
@@ -132,6 +132,7 @@ class BaseClass;
 class Block;
 class Class;
 class Enum;
+class ForwardClassDeclaration;
 
 class Use;
 
diff --git a/src/shared/cplusplus/CheckDeclaration.cpp b/src/shared/cplusplus/CheckDeclaration.cpp
index ee9e80ffa66a2e59b76c0713d3ab9f6365a16e22..f8ddde8b48e8b8162ba29888fafd067633dbcf79 100644
--- a/src/shared/cplusplus/CheckDeclaration.cpp
+++ b/src/shared/cplusplus/CheckDeclaration.cpp
@@ -136,6 +136,23 @@ bool CheckDeclaration::visit(SimpleDeclarationAST *ast)
         }
     }
 
+    if (! ast->declarators && ast->decl_specifier_seq && ! ast->decl_specifier_seq->next) {
+        if (ElaboratedTypeSpecifierAST *elab_type_spec = ast->decl_specifier_seq->asElaboratedTypeSpecifier()) {
+            Name *name = semantic()->check(elab_type_spec->name, _scope);
+            ForwardClassDeclaration *symbol =
+                    control()->newForwardClassDeclaration(elab_type_spec->firstToken(),
+                                                          name);
+
+            if (_templateParameters) {
+                symbol->setTemplateParameters(_templateParameters);
+                _templateParameters = 0;
+            }
+
+            _scope->enterSymbol(symbol);
+            return false;
+        }
+    }
+
     List<Declaration *> **decl_it = &ast->symbols;
     for (DeclaratorListAST *it = ast->declarators; it; it = it->next) {
         Name *name = 0;
diff --git a/src/shared/cplusplus/Control.cpp b/src/shared/cplusplus/Control.cpp
index 4d708f4340c5553206984ba155ea2222bd53c500..7f5fd273caeb8027b7d4848d2dabb6a67254431a 100644
--- a/src/shared/cplusplus/Control.cpp
+++ b/src/shared/cplusplus/Control.cpp
@@ -124,6 +124,7 @@ public:
         delete_array_entries(usingNamespaceDirectives);
         delete_array_entries(enums);
         delete_array_entries(usingDeclarations);
+        delete_array_entries(classForwardDeclarations);
     }
 
     NameId *findOrInsertNameId(Identifier *id)
@@ -322,6 +323,14 @@ public:
         return u;
     }
 
+    ForwardClassDeclaration *newForwardClassDeclaration(unsigned sourceLocation, Name *name)
+    {
+        ForwardClassDeclaration *c = new ForwardClassDeclaration(translationUnit,
+                                                                 sourceLocation, name);
+        classForwardDeclarations.push_back(c);
+        return c;
+    }
+
     Enum *newEnum(unsigned sourceLocation, Name *name)
     {
         Enum *e = new Enum(translationUnit,
@@ -477,6 +486,7 @@ public:
     std::vector<UsingNamespaceDirective *> usingNamespaceDirectives;
     std::vector<Enum *> enums;
     std::vector<UsingDeclaration *> usingDeclarations;
+    std::vector<ForwardClassDeclaration *> classForwardDeclarations;
 };
 
 Control::Control()
@@ -632,4 +642,9 @@ UsingNamespaceDirective *Control::newUsingNamespaceDirective(unsigned sourceLoca
 UsingDeclaration *Control::newUsingDeclaration(unsigned sourceLocation, Name *name)
 { return d->newUsingDeclaration(sourceLocation, name); }
 
+ForwardClassDeclaration *Control::newForwardClassDeclaration(unsigned sourceLocation,
+                                                             Name *name)
+{ return d->newForwardClassDeclaration(sourceLocation, name); }
+
+
 CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/Control.h b/src/shared/cplusplus/Control.h
index 98c1bacdd29079061706c2a8f75859db52164d15..cb64a888aac739a5cb2b63d71f4207b3b58545a2 100644
--- a/src/shared/cplusplus/Control.h
+++ b/src/shared/cplusplus/Control.h
@@ -148,6 +148,9 @@ public:
     /// Creates a new UsingDeclaration symbol.
     UsingDeclaration *newUsingDeclaration(unsigned sourceLocation, Name *name = 0);
 
+    /// Creates a new ForwardClassDeclaration symbol.
+    ForwardClassDeclaration *newForwardClassDeclaration(unsigned sourceLocation, Name *name = 0);
+
     Identifier *findOrInsertIdentifier(const char *chars, unsigned size);
     Identifier *findOrInsertIdentifier(const char *chars);
 
diff --git a/src/shared/cplusplus/Symbol.cpp b/src/shared/cplusplus/Symbol.cpp
index 8e9ba22bb78f5c034c054c69cb3eede9837e76f1..6effeaa1c7d858d67339c858a6c612efb0348449 100644
--- a/src/shared/cplusplus/Symbol.cpp
+++ b/src/shared/cplusplus/Symbol.cpp
@@ -334,6 +334,9 @@ bool Symbol::isNamespace() const
 bool Symbol::isClass() const
 { return asClass() != 0; }
 
+bool Symbol::isForwardClassDeclaration() const
+{ return asForwardClassDeclaration() != 0; }
+
 bool Symbol::isBlock() const
 { return asBlock() != 0; }
 
diff --git a/src/shared/cplusplus/Symbol.h b/src/shared/cplusplus/Symbol.h
index 2b9a428dce9bcad49254692afad2e7cb4cafb0cc..318cc1ca83b2c14f91ca1ea9d1cffe7938430ff3 100644
--- a/src/shared/cplusplus/Symbol.h
+++ b/src/shared/cplusplus/Symbol.h
@@ -197,6 +197,9 @@ public:
     /// Returns true if this Symbol is a BaseClass.
     bool isBaseClass() const;
 
+    /// Returns true if this Symbol is a ForwardClassDeclaration.
+    bool isForwardClassDeclaration() const;
+
     virtual const ScopedSymbol *asScopedSymbol() const { return 0; }
     virtual const Enum *asEnum() const { return 0; }
     virtual const Function *asFunction() const { return 0; }
@@ -208,6 +211,7 @@ public:
     virtual const Declaration *asDeclaration() const { return 0; }
     virtual const Argument *asArgument() const { return 0; }
     virtual const BaseClass *asBaseClass() const { return 0; }
+    virtual const ForwardClassDeclaration *asForwardClassDeclaration() const { return 0; }
 
     virtual ScopedSymbol *asScopedSymbol() { return 0; }
     virtual Enum *asEnum() { return 0; }
@@ -220,6 +224,7 @@ public:
     virtual Declaration *asDeclaration() { return 0; }
     virtual Argument *asArgument() { return 0; }
     virtual BaseClass *asBaseClass() { return 0; }
+    virtual ForwardClassDeclaration *asForwardClassDeclaration() { return 0; }
 
     /// Returns this Symbol's type.
     virtual FullySpecifiedType type() const = 0;
diff --git a/src/shared/cplusplus/SymbolVisitor.h b/src/shared/cplusplus/SymbolVisitor.h
index f0f4738de7f571ed06454aafa95492a069789914..b7113715858d91be43703f4cd3080eef19fabcd5 100644
--- a/src/shared/cplusplus/SymbolVisitor.h
+++ b/src/shared/cplusplus/SymbolVisitor.h
@@ -82,6 +82,7 @@ public:
     virtual bool visit(Namespace *) { return true; }
     virtual bool visit(Class *) { return true; }
     virtual bool visit(Block *) { return true; }
+    virtual bool visit(ForwardClassDeclaration *) { return true; }
 };
 
 CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/Symbols.cpp b/src/shared/cplusplus/Symbols.cpp
index 6fae11453bf48d61516745528e860f208c50d65c..b8195c7db1861c00730edafd3d24a3f5065e0b5d 100644
--- a/src/shared/cplusplus/Symbols.cpp
+++ b/src/shared/cplusplus/Symbols.cpp
@@ -401,6 +401,53 @@ void BaseClass::setVirtual(bool isVirtual)
 void BaseClass::visitSymbol0(SymbolVisitor *visitor)
 { visitor->visit(this); }
 
+ForwardClassDeclaration::ForwardClassDeclaration(TranslationUnit *translationUnit,
+                                                 unsigned sourceLocation, Name *name)
+    : Symbol(translationUnit, sourceLocation, name),
+      _templateParameters(0)
+{ }
+
+ForwardClassDeclaration::~ForwardClassDeclaration()
+{ delete _templateParameters; }
+
+unsigned ForwardClassDeclaration::templateParameterCount() const
+{
+    if (! _templateParameters)
+        return 0;
+    return _templateParameters->symbolCount();
+}
+
+Symbol *ForwardClassDeclaration::templateParameterAt(unsigned index) const
+{ return _templateParameters->symbolAt(index); }
+
+Scope *ForwardClassDeclaration::templateParameters() const
+{ return _templateParameters; }
+
+void ForwardClassDeclaration::setTemplateParameters(Scope *templateParameters)
+{ _templateParameters = templateParameters; }
+
+FullySpecifiedType ForwardClassDeclaration::type() const
+{ return FullySpecifiedType(const_cast<ForwardClassDeclaration *>(this)); }
+
+bool ForwardClassDeclaration::isEqualTo(const Type *other) const
+{
+    if (const ForwardClassDeclaration *otherClassFwdTy = other->asForwardClassDeclarationType()) {
+        if (name() == otherClassFwdTy->name())
+            return true;
+        else if (name() && otherClassFwdTy->name())
+            return name()->isEqualTo(otherClassFwdTy->name());
+
+        return false;
+    }
+    return false;
+}
+
+void ForwardClassDeclaration::visitSymbol0(SymbolVisitor *visitor)
+{ visitor->visit(this); }
+
+void ForwardClassDeclaration::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
 Class::Class(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name)
     : ScopedSymbol(translationUnit, sourceLocation, name),
       _key(ClassKey),
diff --git a/src/shared/cplusplus/Symbols.h b/src/shared/cplusplus/Symbols.h
index 2153b55393e8e925a29a4393e8deac69e626d718..1253621fec3b60e1f507205b0d231219bda04cef 100644
--- a/src/shared/cplusplus/Symbols.h
+++ b/src/shared/cplusplus/Symbols.h
@@ -199,6 +199,42 @@ protected:
     virtual void visitSymbol0(SymbolVisitor *visitor);
 };
 
+class CPLUSPLUS_EXPORT ForwardClassDeclaration: public Symbol, public Type
+{
+public:
+    ForwardClassDeclaration(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name);
+    virtual ~ForwardClassDeclaration();
+
+    unsigned templateParameterCount() const;
+    Symbol *templateParameterAt(unsigned index) const;
+
+    Scope *templateParameters() const;
+    void setTemplateParameters(Scope *templateParameters);
+
+    virtual FullySpecifiedType type() const;
+
+    virtual bool isEqualTo(const Type *other) const;
+
+    virtual const ForwardClassDeclaration *asForwardClassDeclaration() const
+    { return this; }
+
+    virtual ForwardClassDeclaration *asForwardClassDeclaration()
+    { return this; }
+
+    virtual const ForwardClassDeclaration *asForwardClassDeclarationType() const
+    { return this; }
+
+    virtual ForwardClassDeclaration *asForwardClassDeclarationType()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+    virtual void accept0(TypeVisitor *visitor);
+
+private:
+    Scope *_templateParameters;
+};
+
 class CPLUSPLUS_EXPORT Enum: public ScopedSymbol, public Type
 {
 public:
@@ -295,7 +331,6 @@ protected:
     virtual void accept0(TypeVisitor *visitor);
 
 private:
-    Name *_name;
     Scope *_templateParameters;
     FullySpecifiedType _returnType;
     union {
diff --git a/src/shared/cplusplus/Type.cpp b/src/shared/cplusplus/Type.cpp
index b88b0afab4881efe7ad7f8a185b55b2fb6fd77df..f2128f03e80160c8a3754f5a306ffa5312452172 100644
--- a/src/shared/cplusplus/Type.cpp
+++ b/src/shared/cplusplus/Type.cpp
@@ -102,6 +102,9 @@ bool Type::isClassType() const
 bool Type::isEnumType() const
 { return asEnumType() != 0; }
 
+bool Type::isForwardClassDeclarationType() const
+{ return asForwardClassDeclarationType() != 0; }
+
 void Type::accept(TypeVisitor *visitor)
 {
     if (visitor->preVisit(this))
diff --git a/src/shared/cplusplus/Type.h b/src/shared/cplusplus/Type.h
index 320555b40cfd96cf0f7a2f47c87a7d97d1f30a8c..1ac54f4dfbe39d4b1566fc41ac207869ac93951e 100644
--- a/src/shared/cplusplus/Type.h
+++ b/src/shared/cplusplus/Type.h
@@ -80,6 +80,7 @@ public:
     bool isNamespaceType() const;
     bool isClassType() const;
     bool isEnumType() const;
+    bool isForwardClassDeclarationType() const;
 
     virtual const VoidType *asVoidType() const { return 0; }
     virtual const IntegerType *asIntegerType() const { return 0; }
@@ -93,6 +94,7 @@ public:
     virtual const Namespace *asNamespaceType() const { return 0; }
     virtual const Class *asClassType() const { return 0; }
     virtual const Enum *asEnumType() const { return 0; }
+    virtual const ForwardClassDeclaration *asForwardClassDeclarationType() const { return 0; }
 
     virtual VoidType *asVoidType() { return 0; }
     virtual IntegerType *asIntegerType() { return 0; }
@@ -106,6 +108,7 @@ public:
     virtual Namespace *asNamespaceType() { return 0; }
     virtual Class *asClassType() { return 0; }
     virtual Enum *asEnumType() { return 0; }
+    virtual ForwardClassDeclaration *asForwardClassDeclarationType() { return 0; }
 
     void accept(TypeVisitor *visitor);
     static void accept(Type *type, TypeVisitor *visitor);
diff --git a/src/shared/cplusplus/TypeVisitor.h b/src/shared/cplusplus/TypeVisitor.h
index 16fb37c4ad0a5130bd7086ac7f1be159d71e1d6c..41cc57515756dd5bdfdabcd0d43015470d01baf0 100644
--- a/src/shared/cplusplus/TypeVisitor.h
+++ b/src/shared/cplusplus/TypeVisitor.h
@@ -84,6 +84,7 @@ public:
     virtual void visit(Namespace *) {}
     virtual void visit(Class *) {}
     virtual void visit(Enum *) {}
+    virtual void visit(ForwardClassDeclaration *) {}
 };
 
 CPLUSPLUS_END_NAMESPACE