diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp
index 0c1820802aa4680470be38927545172985fdb610..813d84c5e78e76566cd0bad7396a3cdb5bcd8548 100644
--- a/src/plugins/debugger/lldb/lldbengine.cpp
+++ b/src/plugins/debugger/lldb/lldbengine.cpp
@@ -70,6 +70,11 @@
 namespace Debugger {
 namespace Internal {
 
+static QByteArray tooltipIName(const QString &exp)
+{
+    return "tooltip." + exp.toLatin1().toHex();
+}
+
 ///////////////////////////////////////////////////////////////////////
 //
 // LldbEngine
@@ -114,6 +119,29 @@ void LldbEngine::runCommand(const Command &command)
     m_lldbProc.write(cmd);
 }
 
+void LldbEngine::showToolTip()
+{
+    if (m_toolTipContext.isNull())
+        return;
+    const QString expression = m_toolTipContext->expression;
+    if (DebuggerToolTipManager::debug())
+        qDebug() << "GdbEngine::showToolTip " << expression << m_toolTipContext->iname << (*m_toolTipContext);
+
+    if (m_toolTipContext->iname.startsWith("tooltip")
+        && (!debuggerCore()->boolSetting(UseToolTipsInMainEditor)
+            || !watchHandler()->isValidToolTip(m_toolTipContext->iname))) {
+        watchHandler()->removeData(m_toolTipContext->iname);
+        return;
+    }
+
+    DebuggerToolTipWidget *tw = new DebuggerToolTipWidget;
+    tw->setContext(*m_toolTipContext);
+    tw->acquireEngine(this);
+    DebuggerToolTipManager::showToolTip(m_toolTipContext->mousePosition, tw);
+    // Prevent tooltip from re-occurring (classic GDB, QTCREATORBUG-4711).
+    m_toolTipContext.reset();
+}
+
 void LldbEngine::shutdownInferior()
 {
     QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state());
@@ -636,78 +664,57 @@ static QPoint m_toolTipPos;
 static QHash<QString, WatchData> m_toolTipCache;
 
 bool LldbEngine::setToolTipExpression(const QPoint &mousePos,
-    TextEditor::ITextEditor *editor, const DebuggerToolTipContext &ctx)
+    TextEditor::ITextEditor *editor, const DebuggerToolTipContext &contextIn)
 {
-    Q_UNUSED(mousePos);
-    Q_UNUSED(editor);
-
-    if (state() != InferiorStopOk) {
-        //SDEBUG("SUPPRESSING DEBUGGER TOOLTIP, INFERIOR NOT STOPPED");
+    if (state() != InferiorStopOk || !isCppEditor(editor)) {
+        //qDebug() << "SUPPRESSING DEBUGGER TOOLTIP, INFERIOR NOT STOPPED "
+        // " OR NOT A CPPEDITOR";
         return false;
     }
-    // Check mime type and get expression (borrowing some C++ - functions)
-    const QString javaPythonMimeType =
-        QLatin1String("application/javascript");
-    if (!editor->document() || editor->document()->mimeType() != javaPythonMimeType)
-        return false;
-
-    int line;
-    int column;
-    QString exp = cppExpressionAt(editor, ctx.position, &line, &column);
 
-/*
-    if (m_toolTipCache.contains(exp)) {
-        const WatchData & data = m_toolTipCache[exp];
-        q->watchHandler()->removeChildren(data.iname);
-        insertData(data);
-        return;
-    }
-*/
-
-    QToolTip::hideText();
-    if (exp.isEmpty() || exp.startsWith(QLatin1Char('#')))  {
-        QToolTip::hideText();
+    DebuggerToolTipContext context = contextIn;
+    int line, column;
+    QString exp = fixCppExpression(cppExpressionAt(editor, context.position, &line, &column, &context.function));
+    if (exp.isEmpty())
         return false;
+    // Prefer a filter on an existing local variable if it can be found.
+    QByteArray iname;
+    if (const WatchData *localVariable = watchHandler()->findCppLocalVariable(exp)) {
+        exp = QLatin1String(localVariable->exp);
+        iname = localVariable->iname;
+    } else {
+        iname = tooltipIName(exp);
     }
 
-    if (!hasLetterOrNumber(exp)) {
-        QToolTip::showText(m_toolTipPos, tr("\"%1\" contains no identifier.").arg(exp));
+    if (DebuggerToolTipManager::debug())
+        qDebug() << "GdbEngine::setToolTipExpression1 " << exp << iname << context;
+
+    // Same expression: Display synchronously.
+    if (!m_toolTipContext.isNull() && m_toolTipContext->expression == exp) {
+        showToolTip();
         return true;
     }
 
-    if (exp.startsWith(QLatin1Char('"')) && exp.endsWith(QLatin1Char('"'))) {
-        QToolTip::showText(m_toolTipPos, tr("String literal %1").arg(exp));
+    m_toolTipContext.reset(new DebuggerToolTipContext(context));
+    m_toolTipContext->mousePosition = mousePos;
+    m_toolTipContext->expression = exp;
+    m_toolTipContext->iname = iname;
+    // Local variable: Display synchronously.
+    if (iname.startsWith("local")) {
+        showToolTip();
         return true;
     }
 
-    if (exp.startsWith(QLatin1String("++")) || exp.startsWith(QLatin1String("--")))
-        exp.remove(0, 2);
+    if (DebuggerToolTipManager::debug())
+        qDebug() << "GdbEngine::setToolTipExpression2 " << exp << (*m_toolTipContext);
 
-    if (exp.endsWith(QLatin1String("++")) || exp.endsWith(QLatin1String("--")))
-        exp.remove(0, 2);
+    UpdateParameters params;
+    params.tryPartial = true;
+    params.tooltipOnly = true;
+    params.varList = iname;
+    doUpdateLocals(params);
 
-    if (exp.startsWith(QLatin1Char('<')) || exp.startsWith(QLatin1Char('[')))
-        return false;
-
-    if (hasSideEffects(exp)) {
-        QToolTip::showText(m_toolTipPos,
-            tr("Cowardly refusing to evaluate expression \"%1\" "
-               "with potential side effects.").arg(exp));
-        return true;
-    }
-
-#if 0
-    //if (status() != InferiorStopOk)
-    //    return;
-
-    // FIXME: 'exp' can contain illegal characters
-    m_toolTip = WatchData();
-    m_toolTip.exp = exp;
-    m_toolTip.name = exp;
-    m_toolTip.iname = tooltipIName;
-    insertData(m_toolTip);
-#endif
-    return false;
+    return true;
 }
 
 void LldbEngine::updateAll()
@@ -739,6 +746,12 @@ void LldbEngine::updateWatchData(const WatchData &data, const WatchUpdateFlags &
 }
 
 void LldbEngine::updateLocals()
+{
+    UpdateParameters params;
+    doUpdateLocals(params);
+}
+
+void LldbEngine::doUpdateLocals(UpdateParameters params)
 {
     WatchHandler *handler = watchHandler();
 
@@ -747,54 +760,56 @@ void LldbEngine::updateLocals()
     cmd.arg("typeformats", handler->typeFormatRequests());
     cmd.arg("formats", handler->individualFormatRequests());
 
-//    const QString fileName = stackHandler()->currentFrame().file;
-//    if (!fileName.isEmpty()) {
-//        const QString function = stackHandler()->currentFrame().function;
-//        typedef DebuggerToolTipManager::ExpressionInamePair ExpressionInamePair;
-//        typedef DebuggerToolTipManager::ExpressionInamePairs ExpressionInamePairs;
-
-//        // Re-create tooltip items that are not filters on existing local variables in
-//        // the tooltip model.
-//        ExpressionInamePairs toolTips = DebuggerToolTipManager::instance()
-//                ->treeWidgetExpressions(fileName, objectName(), function);
-
-//        const QString currentExpression = tooltipExpression();
-//        if (!currentExpression.isEmpty()) {
-//            int currentIndex = -1;
-//            for (int i = 0; i < toolTips.size(); ++i) {
-//                if (toolTips.at(i).first == currentExpression) {
-//                    currentIndex = i;
-//                    break;
-//                }
-//            }
-//            if (currentIndex < 0)
-//                toolTips.push_back(ExpressionInamePair(currentExpression, tooltipIName(currentExpression)));
-//        }
-
-//        foreach (const ExpressionInamePair &p, toolTips) {
-//            if (p.second.startsWith("tooltip")) {
-//                QHash<QByteArray, QByteArray> hash;
-//                hash["exp"] = p.first.toLatin1();
-//                hash["id"] = p.second;
-//                watcherData.append(Command::toData(hash));
-//            }
-//        }
-//    }
-
     const static bool alwaysVerbose = !qgetenv("QTC_DEBUGGER_PYTHON_VERBOSE").isEmpty();
     cmd.arg("passexceptions", alwaysVerbose);
     cmd.arg("fancy", debuggerCore()->boolSetting(UseDebuggingHelpers));
     cmd.arg("autoderef", debuggerCore()->boolSetting(AutoDerefPointers));
     cmd.arg("dyntype", debuggerCore()->boolSetting(UseDynamicType));
+    cmd.arg("partial", params.tryPartial);
+    cmd.arg("tooltiponly", params.tooltipOnly);
 
     cmd.beginList("watchers");
+    // Watchers
     QHashIterator<QByteArray, int> it(WatchHandler::watcherNames());
     while (it.hasNext()) {
         it.next();
         cmd.beginGroup()
             .arg("iname", "watch." + QByteArray::number(it.value()))
             .arg("exp", it.key().toHex())
-            .endGroup();
+        .endGroup();
+    }
+    // Tooltip
+    const StackFrame frame = stackHandler()->currentFrame();
+    if (!frame.file.isEmpty()) {
+        // Re-create tooltip items that are not filters on existing local variables in
+        // the tooltip model.
+        DebuggerToolTipContexts toolTips =
+            DebuggerToolTipManager::treeWidgetExpressions(frame.file, objectName(), frame.function);
+
+        const QString currentExpression =
+             m_toolTipContext.isNull() ? QString() : m_toolTipContext->expression;
+        if (!currentExpression.isEmpty()) {
+            int currentIndex = -1;
+            for (int i = 0; i < toolTips.size(); ++i) {
+                if (toolTips.at(i).expression == currentExpression) {
+                    currentIndex = i;
+                    break;
+                }
+            }
+            if (currentIndex < 0) {
+                DebuggerToolTipContext context;
+                context.expression = currentExpression;
+                context.iname = tooltipIName(currentExpression);
+                toolTips.push_back(context);
+            }
+        }
+        foreach (const DebuggerToolTipContext &p, toolTips) {
+            if (p.iname.startsWith("tooltip"))
+                cmd.beginGroup()
+                    .arg("iname", p.iname)
+                    .arg("exp", p.expression.toLatin1().toHex())
+                .endGroup();
+        }
     }
     cmd.endList();
 
diff --git a/src/plugins/debugger/lldb/lldbengine.h b/src/plugins/debugger/lldb/lldbengine.h
index 17f36497d89db6975f4562a4f171a6e0146ed8f4..3dd3d69bc3d2f1567c047fc6ec159ee58448febd 100644
--- a/src/plugins/debugger/lldb/lldbengine.h
+++ b/src/plugins/debugger/lldb/lldbengine.h
@@ -33,6 +33,7 @@
 #include <debugger/debuggerengine.h>
 #include <debugger/disassembleragent.h>
 #include <debugger/memoryagent.h>
+#include <debugger/watchhandler.h>
 
 #include <QPointer>
 #include <QProcess>
@@ -157,6 +158,7 @@ private:
     Q_SLOT void runEngine2();
     Q_SLOT void updateAll();
     Q_SLOT void updateLocals();
+    void doUpdateLocals(UpdateParameters params);
     void refreshAll(const GdbMi &all);
     void refreshThreads(const GdbMi &threads);
     void refreshStack(const GdbMi &stack);
@@ -201,6 +203,9 @@ private:
     QMap<QPointer<DisassemblerAgent>, int> m_disassemblerAgents;
     QMap<QPointer<MemoryAgent>, int> m_memoryAgents;
     QHash<int, QPointer<QObject> > m_memoryAgentTokens;
+    QScopedPointer<DebuggerToolTipContext> m_toolTipContext;
+
+    void showToolTip();
 };
 
 } // namespace Internal