diff --git a/src/libs/utils/htmldocextractor.cpp b/src/libs/utils/htmldocextractor.cpp
index 2edb4c8385043d46d713cee39e0b1538999d5dd8..90d2ee6e0ff6c58c82c04bd2db33fac30be0e9e8 100644
--- a/src/libs/utils/htmldocextractor.cpp
+++ b/src/libs/utils/htmldocextractor.cpp
@@ -96,7 +96,7 @@ QString HtmlDocExtractor::getClassOrNamespaceDescription(const QString &html,
         contents = findByPattern(html, pattern);
     }
     if (!contents.isEmpty())
-        contents.replace(QLatin1String("<h2>Detailed Description</h2>"), name);
+        contents.remove(QLatin1String("Detailed Description"));
 
     formatContents(&contents);
     return contents;
diff --git a/src/plugins/cppeditor/cppeditor.qrc b/src/plugins/cppeditor/cppeditor.qrc
index 61cf4a08a657ce9feda22212006a46194c4042e3..0df45087536e80e0fa8418c9b8e2b455f8c6c129 100644
--- a/src/plugins/cppeditor/cppeditor.qrc
+++ b/src/plugins/cppeditor/cppeditor.qrc
@@ -5,5 +5,7 @@
         <file>CppEditor.mimetypes.xml</file>
         <file>images/qt_c.png</file>
         <file>images/f1.png</file>
+        <file>images/larrow.png</file>
+        <file>images/rightarrow.png</file>
     </qresource>
 </RCC>
diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp
index 61d3f7a3f7aa250282c640cdf95af1a73fa9a043..2b4f7a3cdc157ee3fd64b77bf97a50443ec00ba7 100644
--- a/src/plugins/cppeditor/cpphoverhandler.cpp
+++ b/src/plugins/cppeditor/cpphoverhandler.cpp
@@ -40,7 +40,6 @@
 #include <texteditor/basetexteditor.h>
 #include <texteditor/displaysettings.h>
 #include <debugger/debuggerconstants.h>
-#include <utils/htmldocextractor.h>
 
 #include <FullySpecifiedType.h>
 #include <Scope.h>
@@ -54,6 +53,8 @@
 
 #include <QtCore/QDir>
 #include <QtCore/QFileInfo>
+#include <QtCore/QtAlgorithms>
+#include <QtCore/QStringBuilder>
 #include <QtGui/QToolTip>
 #include <QtGui/QTextCursor>
 
@@ -81,6 +82,42 @@ namespace {
             ch = doc->characterAt(tc->position());
         }
     }
+
+    void buildClassHierarchyHelper(Symbol *symbol,
+                                   const LookupContext &context,
+                                   const Overview &overview,
+                                   QList<QStringList> *hierarchy) {
+        if (ClassOrNamespace *classSymbol = context.lookupType(symbol)) {
+            const QList<ClassOrNamespace *> &bases = classSymbol->usings();
+            foreach (ClassOrNamespace *baseClass, bases) {
+                const QList<Symbol *> &symbols = baseClass->symbols();
+                foreach (Symbol *baseSymbol, symbols) {
+                    if (baseSymbol->isClass()) {
+                        hierarchy->back().append(overview.prettyName(baseSymbol->name()));
+                        buildClassHierarchyHelper(baseSymbol, context, overview, hierarchy);
+                        hierarchy->append(hierarchy->back());
+                        hierarchy->back().removeLast();
+                    }
+                }
+            }
+        }
+    }
+
+    void buildClassHierarchy(Symbol *symbol,
+                             const LookupContext &context,
+                             const Overview &overview,
+                             QList<QStringList> *hierarchy) {
+        if (hierarchy->isEmpty())
+            hierarchy->append(QStringList());
+        buildClassHierarchyHelper(symbol, context, overview, hierarchy);
+        hierarchy->removeLast();
+    }
+
+    struct ClassHierarchyComp
+    {
+        bool operator()(const QStringList &a, const QStringList &b)
+        { return a.size() < b.size(); }
+    };
 }
 
 CppHoverHandler::CppHoverHandler(QObject *parent)
@@ -127,7 +164,8 @@ void CppHoverHandler::updateContextHelpId(TextEditor::ITextEditor *editor, int p
 
 void CppHoverHandler::showToolTip(TextEditor::ITextEditor *editor, const QPoint &point, int pos)
 {
-    if (!editor)
+    TextEditor::BaseTextEditor *baseEditor = baseTextEditor(editor);
+    if (!baseEditor)
         return;
 
     editor->setContextHelpId(QString());
@@ -143,24 +181,13 @@ void CppHoverHandler::showToolTip(TextEditor::ITextEditor *editor, const QPoint
     if (m_toolTip.isEmpty()) {
         QToolTip::hideText();
     } else {
-        if (m_matchingHelpCandidate != -1) {
-            QString contents;
-            TextEditor::BaseTextEditor *baseEditor = baseTextEditor(editor);
-            if (baseEditor && baseEditor->displaySettings().m_integrateDocsIntoTooltips)
-                contents = getDocContents();
-            if (!contents.isEmpty()) {
-                m_toolTip = contents;
-            } else {
-                m_toolTip = Qt::escape(m_toolTip);
-                m_toolTip.prepend(QLatin1String("<nobr>"));
-                m_toolTip.append(QLatin1String("</nobr>"));
-            }
+        if (!m_classHierarchy.isEmpty())
+            generateDiagramTooltip(baseEditor->displaySettings().m_integrateDocsIntoTooltips);
+        else
+            generateNormalTooltip(baseEditor->displaySettings().m_integrateDocsIntoTooltips);
 
-            m_toolTip = QString(QLatin1String("<table><tr>"
-                                              "<td valign=middle>%1</td>"
-                                              "<td><img src=\":/cppeditor/images/f1.png\"></td>"
-                                              "</tr></table>")).arg(m_toolTip);
-        }
+        if (m_matchingHelpCandidate != -1)
+            addF1ToTooltip();
 
         const QPoint pnt = point - QPoint(0,
 #ifdef Q_WS_WIN
@@ -220,7 +247,7 @@ void CppHoverHandler::identifyMatch(TextEditor::ITextEditor *editor, int pos)
             return;
 
         const LookupItem &lookupItem = lookupItems.first(); // ### TODO: select the best candidate.
-        handleLookupItemMatch(lookupItem, !extraSelectionTooltip);
+        handleLookupItemMatch(lookupItem, typeOfExpression.context(), !extraSelectionTooltip);
     }
 
     evaluateHelpCandidates();
@@ -244,7 +271,7 @@ bool CppHoverHandler::matchIncludeFile(const CPlusPlus::Document::Ptr &document,
         if (includeFile.line() == line) {
             m_toolTip = QDir::toNativeSeparators(includeFile.fileName());
             const QString &fileName = QFileInfo(includeFile.fileName()).fileName();
-            m_helpCandidates.append(HelpCandidate(fileName, fileName, HelpCandidate::Include));
+            m_helpCandidates.append(HelpCandidate(fileName, fileName, HelpCandidate::Brief));
             return true;
         }
     }
@@ -267,7 +294,9 @@ bool CppHoverHandler::matchMacroInUse(const CPlusPlus::Document::Ptr &document,
     return false;
 }
 
-void CppHoverHandler::handleLookupItemMatch(const LookupItem &lookupItem, const bool assignTooltip)
+void CppHoverHandler::handleLookupItemMatch(const LookupItem &lookupItem,
+                                            const LookupContext &context,
+                                            const bool assignTooltip)
 {
     Symbol *matchingDeclaration = lookupItem.declaration();
     FullySpecifiedType matchingType = lookupItem.type();
@@ -286,6 +315,11 @@ void CppHoverHandler::handleLookupItemMatch(const LookupItem &lookupItem, const
             matchingDeclaration->enclosingSymbol()->isEnum()) {
             qualifiedName.append(overview.prettyName(
                     LookupContext::fullyQualifiedName(matchingDeclaration)));
+
+            if (matchingDeclaration->isClass() ||
+                matchingDeclaration->isForwardClassDeclaration()) {
+                buildClassHierarchy(matchingDeclaration, context, overview, &m_classHierarchy);
+            }
         } else {
             qualifiedName.append(overview.prettyName(matchingDeclaration->name()));
         }
@@ -310,15 +344,15 @@ void CppHoverHandler::handleLookupItemMatch(const LookupItem &lookupItem, const
             helpCategory = HelpCandidate::Enum;
         } else if (matchingDeclaration->isTypedef()) {
             helpCategory = HelpCandidate::Typedef;
-        } else if (matchingDeclaration->isStatic() && !matchingDeclaration->isFunction()) {
+        } else if (matchingDeclaration->isStatic() &&
+                   !matchingDeclaration->type()->isFunctionType()) {
             helpCategory = HelpCandidate::Var;
         } else {
             helpCategory = HelpCandidate::Function;
         }
 
         // Help identifiers are simply the name with no signature, arguments or return type.
-        // They might or might not include a qualification. This is why two candidates are
-        // created.
+        // They might or might not include a qualification. This is why two candidates are created.
         overview.setShowArgumentNames(false);
         overview.setShowReturnTypes(false);
         overview.setShowFunctionSignatures(false);
@@ -350,12 +384,16 @@ bool CppHoverHandler::helpIdExists(const QString &helpId) const
     return false;
 }
 
-QString CppHoverHandler::getDocContents()
+QString CppHoverHandler::getDocContents() const
 {
     Q_ASSERT(m_matchingHelpCandidate >= 0);
 
+    return getDocContents(m_helpCandidates.at(m_matchingHelpCandidate));
+}
+
+QString CppHoverHandler::getDocContents(const HelpCandidate &help) const
+{
     QString contents;
-    const HelpCandidate &help = m_helpCandidates.at(m_matchingHelpCandidate);
     QMap<QString, QUrl> helpLinks =
         Core::HelpManager::instance()->linksForIdentifier(help.m_helpId);
     foreach (const QUrl &url, helpLinks) {
@@ -363,15 +401,14 @@ QString CppHoverHandler::getDocContents()
         const QString &name = removeQualificationIfAny(help.m_helpId);
         const QByteArray &html = Core::HelpManager::instance()->fileData(url);
         switch (help.m_category) {
-        case HelpCandidate::Include:
+        case HelpCandidate::Brief:
             contents = m_htmlDocExtractor.getClassOrNamespaceBrief(html, name);
             break;
         case HelpCandidate::ClassOrNamespace:
             contents = m_htmlDocExtractor.getClassOrNamespaceDescription(html, name);
             break;
         case HelpCandidate::Function:
-            contents =
-                m_htmlDocExtractor.getFunctionDescription(html, help.m_markId, name);
+            contents = m_htmlDocExtractor.getFunctionDescription(html, help.m_markId, name);
             break;
         case HelpCandidate::Enum:
             contents = m_htmlDocExtractor.getEnumDescription(html, name);
@@ -395,14 +432,137 @@ QString CppHoverHandler::getDocContents()
     return contents;
 }
 
+void CppHoverHandler::generateDiagramTooltip(const bool integrateDocs)
+{
+    QString clazz = m_toolTip;
+
+    qSort(m_classHierarchy.begin(), m_classHierarchy.end(), ClassHierarchyComp());
+
+    QStringList directBaseClasses;
+    foreach (const QStringList &hierarchy, m_classHierarchy) {
+        if (hierarchy.size() > 1)
+            break;
+        directBaseClasses.append(hierarchy.at(0));
+    }
+
+    QString diagram(QLatin1String("<table>"));
+    for (int i = 0; i < directBaseClasses.size(); ++i) {
+        if (i == 0) {
+            diagram.append(QString(
+                "<tr><td>%1</td><td>"
+                "<img src=\":/cppeditor/images/rightarrow.png\"></td>"
+                "<td>%2</td></tr>").arg(m_toolTip).arg(directBaseClasses.at(i)));
+        } else {
+            diagram.append(QString(
+                "<tr><td></td><td>"
+                "<img src=\":/cppeditor/images/larrow.png\"></td>"
+                "<td>%1</td></tr>").arg(directBaseClasses.at(i)));
+        }
+    }
+    diagram.append(QLatin1String("</table>"));
+    m_toolTip = diagram;
+
+    if (integrateDocs) {
+        if (m_matchingHelpCandidate != -1) {
+            m_toolTip.append(getDocContents());
+        } else {
+            // Look for documented base classes. Diagram the nearest one or the nearest ones (in
+            // the case there are many at the same level).
+            int helpLevel = 0;
+            QList<int> baseClassesWithHelp;
+            for (int i = 0; i < m_classHierarchy.size(); ++i) {
+                const QStringList &hierarchy = m_classHierarchy.at(i);
+                if (helpLevel != 0 && hierarchy.size() != helpLevel)
+                    break;
+
+                const QString &name = hierarchy.last();
+                if (helpIdExists(name)) {
+                    baseClassesWithHelp.append(i);
+                    if (helpLevel == 0)
+                        helpLevel = hierarchy.size();
+                }
+            }
+
+            if (!baseClassesWithHelp.isEmpty()) {
+                // Choose the first one as the help match.
+                QString base = m_classHierarchy.at(baseClassesWithHelp.at(0)).last();
+                HelpCandidate help(base, base, HelpCandidate::ClassOrNamespace);
+                m_helpCandidates.append(help);
+                m_matchingHelpCandidate = m_helpCandidates.size() - 1;
+
+                if (baseClassesWithHelp.size() == 1 && helpLevel == 1) {
+                    m_toolTip.append(getDocContents(help));
+                } else {
+                    foreach (int hierarchyIndex, baseClassesWithHelp) {
+                        m_toolTip.append(QLatin1String("<p>"));
+                        const QStringList &hierarchy = m_classHierarchy.at(hierarchyIndex);
+                        Q_ASSERT(helpLevel <= hierarchy.size());
+
+                        // Following contents are inside tables so they are on the exact same
+                        // alignment as the top level diagram.
+                        diagram = QString(QLatin1String("<table><tr><td>%1</td>")).arg(clazz);
+                        for (int i = 0; i < helpLevel; ++i) {
+                            diagram.append(
+                                QLatin1String("<td><img src=\":/cppeditor/images/rightarrow.png\">"
+                                              "</td><td>") %
+                                hierarchy.at(i) %
+                                QLatin1String("</td>"));
+                        }
+                        diagram.append(QLatin1String("</tr></table>"));
+
+                        base = hierarchy.at(helpLevel - 1);
+                        QString contents =
+                            getDocContents(HelpCandidate(base, base, HelpCandidate::Brief));
+                        if (!contents.isEmpty()) {
+                            m_toolTip.append(diagram % QLatin1String("<table><tr><td>") %
+                                             contents % QLatin1String("</td></tr></table>"));
+                        }
+                        m_toolTip.append(QLatin1String("</p>"));
+                    }
+                }
+            }
+        }
+    }
+}
+
+void CppHoverHandler::generateNormalTooltip(const bool integrateDocs)
+{
+    if (m_matchingHelpCandidate != -1) {
+        QString contents;
+        if (integrateDocs)
+            contents = getDocContents();
+        if (!contents.isEmpty()) {
+            HelpCandidate::Category cat = m_helpCandidates.at(m_matchingHelpCandidate).m_category;
+            if (cat == HelpCandidate::ClassOrNamespace)
+                m_toolTip.append(contents);
+            else
+                m_toolTip = contents;
+        } else {
+            m_toolTip = Qt::escape(m_toolTip);
+            m_toolTip.prepend(QLatin1String("<nobr>"));
+            m_toolTip.append(QLatin1String("</nobr>"));
+        }
+    }
+}
+
+void CppHoverHandler::addF1ToTooltip()
+{
+    m_toolTip = QString(QLatin1String("<table><tr><td valign=middle>%1</td><td>&nbsp;&nbsp;"
+                                      "<img src=\":/cppeditor/images/f1.png\"></td>"
+                                      "</tr></table>")).arg(m_toolTip);
+}
+
 void CppHoverHandler::resetMatchings()
 {
     m_matchingHelpCandidate = -1;
     m_helpCandidates.clear();
     m_toolTip.clear();
+    m_classHierarchy.clear();
 }
 
 TextEditor::BaseTextEditor *CppHoverHandler::baseTextEditor(TextEditor::ITextEditor *editor)
 {
+    if (!editor)
+        return 0;
     return qobject_cast<TextEditor::BaseTextEditor *>(editor->widget());
 }
diff --git a/src/plugins/cppeditor/cpphoverhandler.h b/src/plugins/cppeditor/cpphoverhandler.h
index 84c58733d484e314f788ab988aa943a3da463c7f..59c987d6d5f3d9fda30925314ce966439f5979c2 100644
--- a/src/plugins/cppeditor/cpphoverhandler.h
+++ b/src/plugins/cppeditor/cpphoverhandler.h
@@ -30,12 +30,12 @@
 #ifndef CPPHOVERHANDLER_H
 #define CPPHOVERHANDLER_H
 
+#include <cplusplus/CppDocument.h>
 #include <utils/htmldocextractor.h>
 
 #include <QtCore/QObject>
 #include <QtCore/QList>
-
-#include <cplusplus/CppDocument.h>
+#include <QtCore/QStringList>
 
 QT_BEGIN_NAMESPACE
 class QPoint;
@@ -43,6 +43,7 @@ QT_END_NAMESPACE
 
 namespace CPlusPlus {
 class LookupItem;
+class LookupContext;
 }
 
 namespace Core {
@@ -83,7 +84,7 @@ private:
             Typedef,
             Var,
             Macro,
-            Include,
+            Brief,
             Function
         };
 
@@ -101,11 +102,17 @@ private:
     bool matchIncludeFile(const CPlusPlus::Document::Ptr &document, unsigned line);
     bool matchMacroInUse(const CPlusPlus::Document::Ptr &document, unsigned pos);
     void handleLookupItemMatch(const CPlusPlus::LookupItem &lookupItem,
+                               const CPlusPlus::LookupContext &lookupContext,
                                const bool assignTooltip);
 
     void evaluateHelpCandidates();
     bool helpIdExists(const QString &helpId) const;
-    QString getDocContents();
+    QString getDocContents() const;
+    QString getDocContents(const HelpCandidate &helpCandidate) const;
+
+    void generateDiagramTooltip(const bool integrateDocs);
+    void generateNormalTooltip(const bool integrateDocs);
+    void addF1ToTooltip();
 
     static TextEditor::BaseTextEditor *baseTextEditor(TextEditor::ITextEditor *editor);
 
@@ -113,6 +120,7 @@ private:
     int m_matchingHelpCandidate;
     QList<HelpCandidate> m_helpCandidates;
     QString m_toolTip;
+    QList<QStringList> m_classHierarchy;
     Utils::HtmlDocExtractor m_htmlDocExtractor;
 };
 
diff --git a/src/plugins/cppeditor/images/larrow.png b/src/plugins/cppeditor/images/larrow.png
new file mode 100644
index 0000000000000000000000000000000000000000..02686583044c124fc15a33440d1f2710a7fc252e
Binary files /dev/null and b/src/plugins/cppeditor/images/larrow.png differ
diff --git a/src/plugins/cppeditor/images/rightarrow.png b/src/plugins/cppeditor/images/rightarrow.png
new file mode 100644
index 0000000000000000000000000000000000000000..26b153d2aa9ac2decea3ecf148e4107fac857f4f
Binary files /dev/null and b/src/plugins/cppeditor/images/rightarrow.png differ