diff --git a/src/libs/cplusplus/ASTPath.cpp b/src/libs/cplusplus/ASTPath.cpp
index 0d3fcf726d7ecfa6b4c6e28a44cafb86ffdef661..e4dc4a1bbcc3db139d4d2149f4632858028eb75a 100644
--- a/src/libs/cplusplus/ASTPath.cpp
+++ b/src/libs/cplusplus/ASTPath.cpp
@@ -32,10 +32,10 @@
 #include <cplusplus/AST.h>
 #include <cplusplus/TranslationUnit.h>
 
-#ifdef DEBUG_AST_PATH
+#ifdef WITH_AST_PATH_DUMP
 #  include <QDebug>
 #  include <typeinfo>
-#endif // DEBUG_AST_PATH
+#endif // WITH_AST_PATH_DUMP
 
 using namespace CPlusPlus;
 
@@ -53,14 +53,14 @@ QList<AST *> ASTPath::operator()(int line, int column)
     return _nodes;
 }
 
-#ifdef DEBUG_AST_PATH
+#ifdef WITH_AST_PATH_DUMP
 void ASTPath::dump(const QList<AST *> nodes)
 {
     qDebug() << "ASTPath dump," << nodes.size() << "nodes:";
     for (int i = 0; i < nodes.size(); ++i)
         qDebug() << qPrintable(QString(i + 1, QLatin1Char('-'))) << typeid(*nodes.at(i)).name();
 }
-#endif // DEBUG_AST_PATH
+#endif // WITH_AST_PATH_DUMP
 
 bool ASTPath::preVisit(AST *ast)
 {
diff --git a/src/libs/cplusplus/ASTPath.h b/src/libs/cplusplus/ASTPath.h
index b74ec3f87c2e219f3eade2ac1222ccbb739e1fa0..1bf29d2dc2201bc5589494ec2d56aee277f57abd 100644
--- a/src/libs/cplusplus/ASTPath.h
+++ b/src/libs/cplusplus/ASTPath.h
@@ -38,7 +38,7 @@
 #include <QList>
 #include <QTextCursor>
 
-#undef DEBUG_AST_PATH
+#undef WITH_AST_PATH_DUMP
 
 namespace CPlusPlus {
 
@@ -56,7 +56,7 @@ public:
     /// line and column are 1-based!
     QList<AST *> operator()(int line, int column);
 
-#ifdef DEBUG_AST_PATH
+#ifdef WITH_AST_PATH_DUMP
     static void dump(const QList<AST *> nodes);
 #endif
 
diff --git a/src/plugins/cpptools/builtinindexingsupport.cpp b/src/plugins/cpptools/builtinindexingsupport.cpp
index 3def71feeb93d012206857b34d11aa5fbd004528..e2b4ffb8ee886d86f48b222a61a3d8598a449cee 100644
--- a/src/plugins/cpptools/builtinindexingsupport.cpp
+++ b/src/plugins/cpptools/builtinindexingsupport.cpp
@@ -1,6 +1,7 @@
 #include "builtinindexingsupport.h"
 
 #include "cppmodelmanager.h"
+#include "cpppreprocessor.h"
 #include "searchsymbols.h"
 #include "cpptoolsconstants.h"
 #include "cppprojectfile.h"
diff --git a/src/plugins/cpptools/cppcompletionassist.cpp b/src/plugins/cpptools/cppcompletionassist.cpp
index cae9114ef7e7449fe0e821bbadd0ac11a42c76af..e27761f3a929fe71a4faa7fe02dce360dbcc30ad 100644
--- a/src/plugins/cpptools/cppcompletionassist.cpp
+++ b/src/plugins/cpptools/cppcompletionassist.cpp
@@ -28,8 +28,8 @@
 ****************************************************************************/
 
 #include "cppcompletionassist.h"
-
 #include "cppmodelmanager.h"
+#include "cpptoolsconstants.h"
 #include "cppdoxygen.h"
 
 #include <coreplugin/icore.h>
diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp
index d09ac81655bd0323be8e76c695d0d71208c40121..26bdd65322e612dd946040aae6cf25fdc2a44b70 100644
--- a/src/plugins/cpptools/cppmodelmanager.cpp
+++ b/src/plugins/cpptools/cppmodelmanager.cpp
@@ -28,6 +28,8 @@
 ****************************************************************************/
 
 #include "cppmodelmanager.h"
+#include "cpppreprocessor.h"
+#include "cpptoolsconstants.h"
 
 #include "builtinindexingsupport.h"
 #include "cppcompletionassist.h"
@@ -44,7 +46,6 @@
 #include <projectexplorer/session.h>
 
 #include <extensionsystem/pluginmanager.h>
-#include <utils/hostosinfo.h>
 #include <utils/qtcassert.h>
 
 #include <QCoreApplication>
@@ -53,9 +54,11 @@
 #include <QTimer>
 #include <QTextBlock>
 
-#include <functional>
+#if defined(QTCREATOR_WITH_DUMP_AST) && defined(Q_CC_GNU)
+#define WITH_AST_DUMP
 #include <iostream>
 #include <sstream>
+#endif
 
 namespace CppTools {
 
@@ -96,7 +99,7 @@ using namespace CppTools;
 using namespace CppTools::Internal;
 using namespace CPlusPlus;
 
-#if defined(QTCREATOR_WITH_DUMP_AST) && defined(Q_CC_GNU)
+#ifdef WITH_AST_DUMP
 
 #include <cxxabi.h>
 
@@ -169,421 +172,6 @@ static const char pp_configuration[] =
     "#define __inline inline\n"
     "#define __forceinline inline\n";
 
-CppPreprocessor::CppPreprocessor(QPointer<CppModelManager> modelManager, bool dumpFileNameWhileParsing)
-    : m_snapshot(modelManager->snapshot()),
-      m_modelManager(modelManager),
-      m_dumpFileNameWhileParsing(dumpFileNameWhileParsing),
-      m_preprocess(this, &m_env),
-      m_revision(0)
-{
-    m_preprocess.setKeepComments(true);
-}
-
-CppPreprocessor::~CppPreprocessor()
-{ }
-
-void CppPreprocessor::setRevision(unsigned revision)
-{ m_revision = revision; }
-
-void CppPreprocessor::setWorkingCopy(const CppModelManagerInterface::WorkingCopy &workingCopy)
-{ m_workingCopy = workingCopy; }
-
-void CppPreprocessor::setIncludePaths(const QStringList &includePaths)
-{
-    m_includePaths.clear();
-
-    for (int i = 0; i < includePaths.size(); ++i) {
-        const QString &path = includePaths.at(i);
-
-        if (Utils::HostOsInfo::isMacHost()) {
-            if (i + 1 < includePaths.size() && path.endsWith(QLatin1String(".framework/Headers"))) {
-                const QFileInfo pathInfo(path);
-                const QFileInfo frameworkFileInfo(pathInfo.path());
-                const QString frameworkName = frameworkFileInfo.baseName();
-
-                const QFileInfo nextIncludePath = includePaths.at(i + 1);
-                if (nextIncludePath.fileName() == frameworkName) {
-                    // We got a QtXXX.framework/Headers followed by $QTDIR/include/QtXXX.
-                    // In this case we prefer to include files from $QTDIR/include/QtXXX.
-                    continue;
-                }
-            }
-        }
-        m_includePaths.append(cleanPath(path));
-    }
-}
-
-void CppPreprocessor::setFrameworkPaths(const QStringList &frameworkPaths)
-{
-    m_frameworkPaths.clear();
-
-    foreach (const QString &frameworkPath, frameworkPaths) {
-        addFrameworkPath(frameworkPath);
-    }
-}
-
-// Add the given framework path, and expand private frameworks.
-//
-// Example:
-//  <framework-path>/ApplicationServices.framework
-// has private frameworks in:
-//  <framework-path>/ApplicationServices.framework/Frameworks
-// if the "Frameworks" folder exists inside the top level framework.
-void CppPreprocessor::addFrameworkPath(const QString &frameworkPath)
-{
-    // The algorithm below is a bit too eager, but that's because we're not getting
-    // in the frameworks we're linking against. If we would have that, then we could
-    // add only those private frameworks.
-    QString cleanFrameworkPath = cleanPath(frameworkPath);
-    if (!m_frameworkPaths.contains(cleanFrameworkPath))
-        m_frameworkPaths.append(cleanFrameworkPath);
-
-    const QDir frameworkDir(cleanFrameworkPath);
-    const QStringList filter = QStringList() << QLatin1String("*.framework");
-    foreach (const QFileInfo &framework, frameworkDir.entryInfoList(filter)) {
-        if (!framework.isDir())
-            continue;
-        const QFileInfo privateFrameworks(framework.absoluteFilePath(), QLatin1String("Frameworks"));
-        if (privateFrameworks.exists() && privateFrameworks.isDir())
-            addFrameworkPath(privateFrameworks.absoluteFilePath());
-    }
-}
-
-void CppPreprocessor::setTodo(const QStringList &files)
-{ m_todo = QSet<QString>::fromList(files); }
-
-namespace {
-class Process: public std::unary_function<Document::Ptr, void>
-{
-    QPointer<CppModelManager> _modelManager;
-    Document::Ptr _doc;
-    Document::CheckMode _mode;
-
-public:
-    Process(QPointer<CppModelManager> modelManager,
-            Document::Ptr doc,
-            const CppModelManager::WorkingCopy &workingCopy)
-        : _modelManager(modelManager),
-          _doc(doc),
-          _mode(Document::FastCheck)
-    {
-
-        if (workingCopy.contains(_doc->fileName()))
-            _mode = Document::FullCheck;
-    }
-
-    void operator()()
-    {
-        _doc->check(_mode);
-
-        if (_modelManager)
-            _modelManager->emitDocumentUpdated(_doc);
-
-        _doc->releaseSourceAndAST();
-    }
-};
-} // end of anonymous namespace
-
-void CppPreprocessor::run(const QString &fileName)
-{
-    sourceNeeded(0, fileName, IncludeGlobal);
-}
-
-void CppPreprocessor::removeFromCache(const QString &fileName)
-{
-    m_snapshot.remove(fileName);
-}
-
-void CppPreprocessor::resetEnvironment()
-{
-    m_env.reset();
-    m_processed.clear();
-}
-
-void CppPreprocessor::getFileContents(const QString &absoluteFilePath,
-                                      QString *contents,
-                                      unsigned *revision) const
-{
-    if (absoluteFilePath.isEmpty())
-        return;
-
-    if (m_workingCopy.contains(absoluteFilePath)) {
-        QPair<QString, unsigned> entry = m_workingCopy.get(absoluteFilePath);
-        if (contents)
-            *contents = entry.first;
-        if (revision)
-            *revision = entry.second;
-        return;
-    }
-
-    QFile file(absoluteFilePath);
-    if (file.open(QFile::ReadOnly | QFile::Text)) {
-        QTextCodec *defaultCodec = Core::EditorManager::instance()->defaultTextCodec();
-        QTextStream stream(&file);
-        stream.setCodec(defaultCodec);
-        if (contents)
-            *contents = stream.readAll();
-        if (revision)
-            *revision = 0;
-        file.close();
-    }
-}
-
-bool CppPreprocessor::checkFile(const QString &absoluteFilePath) const
-{
-    if (absoluteFilePath.isEmpty() || m_included.contains(absoluteFilePath))
-        return true;
-
-    QFileInfo fileInfo(absoluteFilePath);
-    return fileInfo.isFile() && fileInfo.isReadable();
-}
-
-/// Resolve the given file name to its absolute path w.r.t. the include type.
-QString CppPreprocessor::resolveFile(const QString &fileName, IncludeType type)
-{
-    if (type == IncludeGlobal) {
-        QHash<QString, QString>::ConstIterator it = m_fileNameCache.find(fileName);
-        if (it != m_fileNameCache.end())
-            return it.value();
-        const QString fn = resolveFile_helper(fileName, type);
-        m_fileNameCache.insert(fileName, fn);
-        return fn;
-    }
-
-    // IncludeLocal, IncludeNext
-    return resolveFile_helper(fileName, type);
-}
-
-QString CppPreprocessor::cleanPath(const QString &path)
-{
-    QString result = QDir::cleanPath(path);
-    const QChar slash(QLatin1Char('/'));
-    if (!result.endsWith(slash))
-        result.append(slash);
-    return result;
-}
-
-QString CppPreprocessor::resolveFile_helper(const QString &fileName, IncludeType type)
-{
-    QFileInfo fileInfo(fileName);
-    if (fileName == Preprocessor::configurationFileName || fileInfo.isAbsolute())
-        return fileName;
-
-    if (type == IncludeLocal && m_currentDoc) {
-        QFileInfo currentFileInfo(m_currentDoc->fileName());
-        QString path = cleanPath(currentFileInfo.absolutePath()) + fileName;
-        if (checkFile(path))
-            return path;
-    }
-
-    foreach (const QString &includePath, m_includePaths) {
-        QString path = includePath + fileName;
-        if (checkFile(path))
-            return path;
-    }
-
-    int index = fileName.indexOf(QLatin1Char('/'));
-    if (index != -1) {
-        QString frameworkName = fileName.left(index);
-        QString name = frameworkName + QLatin1String(".framework/Headers/") + fileName.mid(index + 1);
-
-        foreach (const QString &frameworkPath, m_frameworkPaths) {
-            QString path = frameworkPath + name;
-            if (checkFile(path))
-                return path;
-        }
-    }
-
-    //qDebug() << "**** file" << fileName << "not found!";
-    return QString();
-}
-
-void CppPreprocessor::macroAdded(const Macro &macro)
-{
-    if (! m_currentDoc)
-        return;
-
-    m_currentDoc->appendMacro(macro);
-}
-
-static inline const Macro revision(const CppModelManagerInterface::WorkingCopy &s, const Macro &macro)
-{
-    Macro newMacro(macro);
-    newMacro.setFileRevision(s.get(macro.fileName()).second);
-    return newMacro;
-}
-
-void CppPreprocessor::passedMacroDefinitionCheck(unsigned offset, unsigned line, const Macro &macro)
-{
-    if (! m_currentDoc)
-        return;
-
-    m_currentDoc->addMacroUse(revision(m_workingCopy, macro), offset, macro.name().length(), line,
-                              QVector<MacroArgumentReference>());
-}
-
-void CppPreprocessor::failedMacroDefinitionCheck(unsigned offset, const ByteArrayRef &name)
-{
-    if (! m_currentDoc)
-        return;
-
-    m_currentDoc->addUndefinedMacroUse(QByteArray(name.start(), name.size()), offset);
-}
-
-void CppPreprocessor::notifyMacroReference(unsigned offset, unsigned line, const Macro &macro)
-{
-    if (! m_currentDoc)
-        return;
-
-    m_currentDoc->addMacroUse(revision(m_workingCopy, macro), offset, macro.name().length(), line,
-                              QVector<MacroArgumentReference>());
-}
-
-void CppPreprocessor::startExpandingMacro(unsigned offset, unsigned line,
-                                          const Macro &macro,
-                                          const QVector<MacroArgumentReference> &actuals)
-{
-    if (! m_currentDoc)
-        return;
-
-    m_currentDoc->addMacroUse(revision(m_workingCopy, macro), offset, macro.name().length(), line, actuals);
-}
-
-void CppPreprocessor::stopExpandingMacro(unsigned, const Macro &)
-{
-    if (! m_currentDoc)
-        return;
-
-    //qDebug() << "stop expanding:" << macro.name;
-}
-
-void CppPreprocessor::markAsIncludeGuard(const QByteArray &macroName)
-{
-    if (!m_currentDoc)
-        return;
-
-    m_currentDoc->setIncludeGuardMacroName(macroName);
-}
-
-void CppPreprocessor::mergeEnvironment(Document::Ptr doc)
-{
-    if (! doc)
-        return;
-
-    const QString fn = doc->fileName();
-
-    if (m_processed.contains(fn))
-        return;
-
-    m_processed.insert(fn);
-
-    foreach (const Document::Include &incl, doc->includes()) {
-        QString includedFile = incl.fileName();
-
-        if (Document::Ptr includedDoc = m_snapshot.document(includedFile))
-            mergeEnvironment(includedDoc);
-        else
-            run(includedFile);
-    }
-
-    m_env.addMacros(doc->definedMacros());
-}
-
-void CppPreprocessor::startSkippingBlocks(unsigned offset)
-{
-    //qDebug() << "start skipping blocks:" << offset;
-    if (m_currentDoc)
-        m_currentDoc->startSkippingBlocks(offset);
-}
-
-void CppPreprocessor::stopSkippingBlocks(unsigned offset)
-{
-    //qDebug() << "stop skipping blocks:" << offset;
-    if (m_currentDoc)
-        m_currentDoc->stopSkippingBlocks(offset);
-}
-
-void CppPreprocessor::sourceNeeded(unsigned line, const QString &fileName, IncludeType type)
-{
-    if (fileName.isEmpty())
-        return;
-
-    QString absoluteFileName = resolveFile(fileName, type);
-    absoluteFileName = QDir::cleanPath(absoluteFileName);
-    if (m_currentDoc && !absoluteFileName.isEmpty())
-        m_currentDoc->addIncludeFile(absoluteFileName, line);
-    if (m_included.contains(absoluteFileName))
-        return; // we've already seen this file.
-    if (absoluteFileName != modelManager()->configurationFileName())
-        m_included.insert(absoluteFileName);
-
-    unsigned editorRevision = 0;
-    QString contents;
-    getFileContents(absoluteFileName, &contents, &editorRevision);
-    if (m_currentDoc) {
-        if (contents.isEmpty() && ! QFileInfo(absoluteFileName).isAbsolute()) {
-            QString msg = QCoreApplication::translate(
-                    "CppPreprocessor", "%1: No such file or directory").arg(fileName);
-
-            Document::DiagnosticMessage d(Document::DiagnosticMessage::Warning,
-                                          m_currentDoc->fileName(),
-                                          line, /*column = */ 0,
-                                          msg);
-
-            m_currentDoc->addDiagnosticMessage(d);
-
-            //qWarning() << "file not found:" << fileName << m_currentDoc->fileName() << env.current_line;
-
-            return;
-        }
-    }
-
-    if (m_dumpFileNameWhileParsing) {
-        qDebug() << "Parsing file:" << absoluteFileName
-//             << "contents:" << contents.size()
-                    ;
-    }
-
-    Document::Ptr doc = m_snapshot.document(absoluteFileName);
-    if (doc) {
-        mergeEnvironment(doc);
-        return;
-    }
-
-    doc = Document::create(absoluteFileName);
-    doc->setRevision(m_revision);
-    doc->setEditorRevision(editorRevision);
-
-    QFileInfo info(absoluteFileName);
-    if (info.exists())
-        doc->setLastModified(info.lastModified());
-
-    Document::Ptr previousDoc = switchDocument(doc);
-
-    const QByteArray preprocessedCode = m_preprocess.run(absoluteFileName, contents);
-
-//    { QByteArray b(preprocessedCode); b.replace("\n", "<<<\n"); qDebug("Preprocessed code for \"%s\": [[%s]]", fileName.toUtf8().constData(), b.constData()); }
-
-    doc->setUtf8Source(preprocessedCode);
-    doc->keepSourceAndAST();
-    doc->tokenize();
-
-    m_snapshot.insert(doc);
-    m_todo.remove(absoluteFileName);
-
-    Process process(m_modelManager, doc, m_workingCopy);
-    process();
-
-    (void) switchDocument(previousDoc);
-}
-
-Document::Ptr CppPreprocessor::switchDocument(Document::Ptr doc)
-{
-    Document::Ptr previousDoc = m_currentDoc;
-    m_currentDoc = doc;
-    return previousDoc;
-}
-
 void CppModelManager::updateModifiedSourceFiles()
 {
     const Snapshot snapshot = this->snapshot();
diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h
index d347b851e53c0a64f46929078a81772c5cab2c62..e78729958f498524f0c999b4ae4babd9958b3e71 100644
--- a/src/plugins/cpptools/cppmodelmanager.h
+++ b/src/plugins/cpptools/cppmodelmanager.h
@@ -31,15 +31,11 @@
 #define CPPMODELMANAGER_H
 
 #include "cpptools_global.h"
-#include "cpptoolsconstants.h"
 #include "cppmodelmanagerinterface.h"
 
 #include <projectexplorer/project.h>
 #include <texteditor/basetexteditor.h>
 
-#include <cplusplus/PreprocessorEnvironment.h>
-#include <cplusplus/pp-engine.h>
-
 #include <QHash>
 #include <QMutex>
 
@@ -51,7 +47,6 @@ class BaseTextEditorWidget;
 
 namespace CppTools {
 
-class CppCompletionSupportFactory;
 class CppEditorSupport;
 class CppHighlightingSupportFactory;
 
@@ -205,77 +200,6 @@ private:
     CppIndexingSupport *m_internalIndexingSupport;
 };
 
-class CPPTOOLS_EXPORT CppPreprocessor: public CPlusPlus::Client
-{
-    Q_DISABLE_COPY(CppPreprocessor)
-
-public:
-    CppPreprocessor(QPointer<CppModelManager> modelManager, bool dumpFileNameWhileParsing = false);
-    virtual ~CppPreprocessor();
-
-    void setRevision(unsigned revision);
-    void setWorkingCopy(const CppTools::CppModelManagerInterface::WorkingCopy &workingCopy);
-    void setIncludePaths(const QStringList &includePaths);
-    void setFrameworkPaths(const QStringList &frameworkPaths);
-    void addFrameworkPath(const QString &frameworkPath);
-    void setProjectFiles(const QStringList &files);
-    void setTodo(const QStringList &files);
-
-    void run(const QString &fileName);
-    void removeFromCache(const QString &fileName);
-
-    void resetEnvironment();
-    static QString cleanPath(const QString &path);
-
-    const QSet<QString> &todo() const
-    { return m_todo; }
-
-    CppModelManager *modelManager() const
-    { return m_modelManager.data(); }
-
-protected:
-    CPlusPlus::Document::Ptr switchDocument(CPlusPlus::Document::Ptr doc);
-
-    void getFileContents(const QString &absoluteFilePath, QString *contents, unsigned *revision) const;
-    bool checkFile(const QString &absoluteFilePath) const;
-    QString resolveFile(const QString &fileName, IncludeType type);
-    QString resolveFile_helper(const QString &fileName, IncludeType type);
-
-    void mergeEnvironment(CPlusPlus::Document::Ptr doc);
-
-    virtual void macroAdded(const CPlusPlus::Macro &macro);
-    virtual void passedMacroDefinitionCheck(unsigned offset, unsigned line,
-                                            const CPlusPlus::Macro &macro);
-    virtual void failedMacroDefinitionCheck(unsigned offset, const CPlusPlus::ByteArrayRef &name);
-    virtual void notifyMacroReference(unsigned offset, unsigned line,
-                                      const CPlusPlus::Macro &macro);
-    virtual void startExpandingMacro(unsigned offset,
-                                     unsigned line,
-                                     const CPlusPlus::Macro &macro,
-                                     const QVector<CPlusPlus::MacroArgumentReference> &actuals);
-    virtual void stopExpandingMacro(unsigned offset, const CPlusPlus::Macro &macro);
-    virtual void markAsIncludeGuard(const QByteArray &macroName);
-    virtual void startSkippingBlocks(unsigned offset);
-    virtual void stopSkippingBlocks(unsigned offset);
-    virtual void sourceNeeded(unsigned line, const QString &fileName, IncludeType type);
-
-private:
-    CPlusPlus::Snapshot m_snapshot;
-    QPointer<CppModelManager> m_modelManager;
-    bool m_dumpFileNameWhileParsing;
-    CPlusPlus::Environment m_env;
-    CPlusPlus::Preprocessor m_preprocess;
-    QStringList m_includePaths;
-    CppTools::CppModelManagerInterface::WorkingCopy m_workingCopy;
-    QStringList m_frameworkPaths;
-    QSet<QString> m_included;
-    CPlusPlus::Document::Ptr m_currentDoc;
-    QSet<QString> m_todo;
-    QSet<QString> m_processed;
-    unsigned m_revision;
-    QHash<QString, QString> m_fileNameCache;
-};
-
 } // namespace Internal
 } // namespace CppTools
 
diff --git a/src/plugins/cpptools/cppmodelmanager_test.cpp b/src/plugins/cpptools/cppmodelmanager_test.cpp
index 2a9462674f4bdeb5944e62021d0a08401d92eb8e..3385768c1526850c4392af6e6df42ab0d275e43d 100644
--- a/src/plugins/cpptools/cppmodelmanager_test.cpp
+++ b/src/plugins/cpptools/cppmodelmanager_test.cpp
@@ -29,7 +29,7 @@
 
 #include "cpptoolsplugin.h"
 
-#include "cppmodelmanager.h"
+#include "cpppreprocessor.h"
 #include "modelmanagertesthelper.h"
 
 #include <QtTest>
diff --git a/src/plugins/cpptools/cpppreprocessor.cpp b/src/plugins/cpptools/cpppreprocessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5ab1c9a04e713138ab24299bb41e01eb8ae89d30
--- /dev/null
+++ b/src/plugins/cpptools/cpppreprocessor.cpp
@@ -0,0 +1,425 @@
+#include "cppmodelmanager.h"
+#include "cpppreprocessor.h"
+
+#include <utils/hostosinfo.h>
+
+#include <QCoreApplication>
+
+using namespace CPlusPlus;
+using namespace CppTools;
+using namespace CppTools::Internal;
+
+CppPreprocessor::CppPreprocessor(QPointer<CppModelManager> modelManager, bool dumpFileNameWhileParsing)
+    : m_snapshot(modelManager->snapshot()),
+      m_modelManager(modelManager),
+      m_dumpFileNameWhileParsing(dumpFileNameWhileParsing),
+      m_preprocess(this, &m_env),
+      m_revision(0)
+{
+    m_preprocess.setKeepComments(true);
+}
+
+CppPreprocessor::~CppPreprocessor()
+{ }
+
+void CppPreprocessor::setRevision(unsigned revision)
+{ m_revision = revision; }
+
+void CppPreprocessor::setWorkingCopy(const CppModelManagerInterface::WorkingCopy &workingCopy)
+{ m_workingCopy = workingCopy; }
+
+void CppPreprocessor::setIncludePaths(const QStringList &includePaths)
+{
+    m_includePaths.clear();
+
+    for (int i = 0; i < includePaths.size(); ++i) {
+        const QString &path = includePaths.at(i);
+
+        if (Utils::HostOsInfo::isMacHost()) {
+            if (i + 1 < includePaths.size() && path.endsWith(QLatin1String(".framework/Headers"))) {
+                const QFileInfo pathInfo(path);
+                const QFileInfo frameworkFileInfo(pathInfo.path());
+                const QString frameworkName = frameworkFileInfo.baseName();
+
+                const QFileInfo nextIncludePath = includePaths.at(i + 1);
+                if (nextIncludePath.fileName() == frameworkName) {
+                    // We got a QtXXX.framework/Headers followed by $QTDIR/include/QtXXX.
+                    // In this case we prefer to include files from $QTDIR/include/QtXXX.
+                    continue;
+                }
+            }
+        }
+        m_includePaths.append(cleanPath(path));
+    }
+}
+
+void CppPreprocessor::setFrameworkPaths(const QStringList &frameworkPaths)
+{
+    m_frameworkPaths.clear();
+
+    foreach (const QString &frameworkPath, frameworkPaths) {
+        addFrameworkPath(frameworkPath);
+    }
+}
+
+// Add the given framework path, and expand private frameworks.
+//
+// Example:
+//  <framework-path>/ApplicationServices.framework
+// has private frameworks in:
+//  <framework-path>/ApplicationServices.framework/Frameworks
+// if the "Frameworks" folder exists inside the top level framework.
+void CppPreprocessor::addFrameworkPath(const QString &frameworkPath)
+{
+    // The algorithm below is a bit too eager, but that's because we're not getting
+    // in the frameworks we're linking against. If we would have that, then we could
+    // add only those private frameworks.
+    QString cleanFrameworkPath = cleanPath(frameworkPath);
+    if (!m_frameworkPaths.contains(cleanFrameworkPath))
+        m_frameworkPaths.append(cleanFrameworkPath);
+
+    const QDir frameworkDir(cleanFrameworkPath);
+    const QStringList filter = QStringList() << QLatin1String("*.framework");
+    foreach (const QFileInfo &framework, frameworkDir.entryInfoList(filter)) {
+        if (!framework.isDir())
+            continue;
+        const QFileInfo privateFrameworks(framework.absoluteFilePath(), QLatin1String("Frameworks"));
+        if (privateFrameworks.exists() && privateFrameworks.isDir())
+            addFrameworkPath(privateFrameworks.absoluteFilePath());
+    }
+}
+
+void CppPreprocessor::setTodo(const QStringList &files)
+{ m_todo = QSet<QString>::fromList(files); }
+
+namespace {
+class Process: public std::unary_function<Document::Ptr, void>
+{
+    QPointer<CppModelManager> _modelManager;
+    Document::Ptr _doc;
+    Document::CheckMode _mode;
+
+public:
+    Process(QPointer<CppModelManager> modelManager,
+            Document::Ptr doc,
+            const CppModelManager::WorkingCopy &workingCopy)
+        : _modelManager(modelManager),
+          _doc(doc),
+          _mode(Document::FastCheck)
+    {
+
+        if (workingCopy.contains(_doc->fileName()))
+            _mode = Document::FullCheck;
+    }
+
+    void operator()()
+    {
+        _doc->check(_mode);
+
+        if (_modelManager)
+            _modelManager->emitDocumentUpdated(_doc);
+
+        _doc->releaseSourceAndAST();
+    }
+};
+} // end of anonymous namespace
+
+void CppPreprocessor::run(const QString &fileName)
+{
+    sourceNeeded(0, fileName, IncludeGlobal);
+}
+
+void CppPreprocessor::removeFromCache(const QString &fileName)
+{
+    m_snapshot.remove(fileName);
+}
+
+void CppPreprocessor::resetEnvironment()
+{
+    m_env.reset();
+    m_processed.clear();
+}
+
+void CppPreprocessor::getFileContents(const QString &absoluteFilePath,
+                                      QString *contents,
+                                      unsigned *revision) const
+{
+    if (absoluteFilePath.isEmpty())
+        return;
+
+    if (m_workingCopy.contains(absoluteFilePath)) {
+        QPair<QString, unsigned> entry = m_workingCopy.get(absoluteFilePath);
+        if (contents)
+            *contents = entry.first;
+        if (revision)
+            *revision = entry.second;
+        return;
+    }
+
+    QFile file(absoluteFilePath);
+    if (file.open(QFile::ReadOnly | QFile::Text)) {
+        QTextCodec *defaultCodec = Core::EditorManager::instance()->defaultTextCodec();
+        QTextStream stream(&file);
+        stream.setCodec(defaultCodec);
+        if (contents)
+            *contents = stream.readAll();
+        if (revision)
+            *revision = 0;
+        file.close();
+    }
+}
+
+bool CppPreprocessor::checkFile(const QString &absoluteFilePath) const
+{
+    if (absoluteFilePath.isEmpty() || m_included.contains(absoluteFilePath))
+        return true;
+
+    QFileInfo fileInfo(absoluteFilePath);
+    return fileInfo.isFile() && fileInfo.isReadable();
+}
+
+/// Resolve the given file name to its absolute path w.r.t. the include type.
+QString CppPreprocessor::resolveFile(const QString &fileName, IncludeType type)
+{
+    if (type == IncludeGlobal) {
+        QHash<QString, QString>::ConstIterator it = m_fileNameCache.find(fileName);
+        if (it != m_fileNameCache.end())
+            return it.value();
+        const QString fn = resolveFile_helper(fileName, type);
+        m_fileNameCache.insert(fileName, fn);
+        return fn;
+    }
+
+    // IncludeLocal, IncludeNext
+    return resolveFile_helper(fileName, type);
+}
+
+QString CppPreprocessor::cleanPath(const QString &path)
+{
+    QString result = QDir::cleanPath(path);
+    const QChar slash(QLatin1Char('/'));
+    if (!result.endsWith(slash))
+        result.append(slash);
+    return result;
+}
+
+QString CppPreprocessor::resolveFile_helper(const QString &fileName, IncludeType type)
+{
+    QFileInfo fileInfo(fileName);
+    if (fileName == Preprocessor::configurationFileName || fileInfo.isAbsolute())
+        return fileName;
+
+    if (type == IncludeLocal && m_currentDoc) {
+        QFileInfo currentFileInfo(m_currentDoc->fileName());
+        QString path = cleanPath(currentFileInfo.absolutePath()) + fileName;
+        if (checkFile(path))
+            return path;
+    }
+
+    foreach (const QString &includePath, m_includePaths) {
+        QString path = includePath + fileName;
+        if (checkFile(path))
+            return path;
+    }
+
+    int index = fileName.indexOf(QLatin1Char('/'));
+    if (index != -1) {
+        QString frameworkName = fileName.left(index);
+        QString name = frameworkName + QLatin1String(".framework/Headers/") + fileName.mid(index + 1);
+
+        foreach (const QString &frameworkPath, m_frameworkPaths) {
+            QString path = frameworkPath + name;
+            if (checkFile(path))
+                return path;
+        }
+    }
+
+    //qDebug() << "**** file" << fileName << "not found!";
+    return QString();
+}
+
+void CppPreprocessor::macroAdded(const Macro &macro)
+{
+    if (! m_currentDoc)
+        return;
+
+    m_currentDoc->appendMacro(macro);
+}
+
+static inline const Macro revision(const CppModelManagerInterface::WorkingCopy &s, const Macro &macro)
+{
+    Macro newMacro(macro);
+    newMacro.setFileRevision(s.get(macro.fileName()).second);
+    return newMacro;
+}
+
+void CppPreprocessor::passedMacroDefinitionCheck(unsigned offset, unsigned line, const Macro &macro)
+{
+    if (! m_currentDoc)
+        return;
+
+    m_currentDoc->addMacroUse(revision(m_workingCopy, macro), offset, macro.name().length(), line,
+                              QVector<MacroArgumentReference>());
+}
+
+void CppPreprocessor::failedMacroDefinitionCheck(unsigned offset, const ByteArrayRef &name)
+{
+    if (! m_currentDoc)
+        return;
+
+    m_currentDoc->addUndefinedMacroUse(QByteArray(name.start(), name.size()), offset);
+}
+
+void CppPreprocessor::notifyMacroReference(unsigned offset, unsigned line, const Macro &macro)
+{
+    if (! m_currentDoc)
+        return;
+
+    m_currentDoc->addMacroUse(revision(m_workingCopy, macro), offset, macro.name().length(), line,
+                              QVector<MacroArgumentReference>());
+}
+
+void CppPreprocessor::startExpandingMacro(unsigned offset, unsigned line,
+                                          const Macro &macro,
+                                          const QVector<MacroArgumentReference> &actuals)
+{
+    if (! m_currentDoc)
+        return;
+
+    m_currentDoc->addMacroUse(revision(m_workingCopy, macro), offset, macro.name().length(), line, actuals);
+}
+
+void CppPreprocessor::stopExpandingMacro(unsigned, const Macro &)
+{
+    if (! m_currentDoc)
+        return;
+
+    //qDebug() << "stop expanding:" << macro.name;
+}
+
+void CppPreprocessor::markAsIncludeGuard(const QByteArray &macroName)
+{
+    if (!m_currentDoc)
+        return;
+
+    m_currentDoc->setIncludeGuardMacroName(macroName);
+}
+
+void CppPreprocessor::mergeEnvironment(Document::Ptr doc)
+{
+    if (! doc)
+        return;
+
+    const QString fn = doc->fileName();
+
+    if (m_processed.contains(fn))
+        return;
+
+    m_processed.insert(fn);
+
+    foreach (const Document::Include &incl, doc->includes()) {
+        QString includedFile = incl.fileName();
+
+        if (Document::Ptr includedDoc = m_snapshot.document(includedFile))
+            mergeEnvironment(includedDoc);
+        else
+            run(includedFile);
+    }
+
+    m_env.addMacros(doc->definedMacros());
+}
+
+void CppPreprocessor::startSkippingBlocks(unsigned offset)
+{
+    //qDebug() << "start skipping blocks:" << offset;
+    if (m_currentDoc)
+        m_currentDoc->startSkippingBlocks(offset);
+}
+
+void CppPreprocessor::stopSkippingBlocks(unsigned offset)
+{
+    //qDebug() << "stop skipping blocks:" << offset;
+    if (m_currentDoc)
+        m_currentDoc->stopSkippingBlocks(offset);
+}
+
+void CppPreprocessor::sourceNeeded(unsigned line, const QString &fileName, IncludeType type)
+{
+    if (fileName.isEmpty())
+        return;
+
+    QString absoluteFileName = resolveFile(fileName, type);
+    absoluteFileName = QDir::cleanPath(absoluteFileName);
+    if (m_currentDoc && !absoluteFileName.isEmpty())
+        m_currentDoc->addIncludeFile(absoluteFileName, line);
+    if (m_included.contains(absoluteFileName))
+        return; // we've already seen this file.
+    if (absoluteFileName != modelManager()->configurationFileName())
+        m_included.insert(absoluteFileName);
+
+    unsigned editorRevision = 0;
+    QString contents;
+    getFileContents(absoluteFileName, &contents, &editorRevision);
+    if (m_currentDoc) {
+        if (contents.isEmpty() && ! QFileInfo(absoluteFileName).isAbsolute()) {
+            QString msg = QCoreApplication::translate(
+                    "CppPreprocessor", "%1: No such file or directory").arg(fileName);
+
+            Document::DiagnosticMessage d(Document::DiagnosticMessage::Warning,
+                                          m_currentDoc->fileName(),
+                                          line, /*column = */ 0,
+                                          msg);
+
+            m_currentDoc->addDiagnosticMessage(d);
+
+            //qWarning() << "file not found:" << fileName << m_currentDoc->fileName() << env.current_line;
+
+            return;
+        }
+    }
+
+    if (m_dumpFileNameWhileParsing) {
+        qDebug() << "Parsing file:" << absoluteFileName
+//             << "contents:" << contents.size()
+                    ;
+    }
+
+    Document::Ptr doc = m_snapshot.document(absoluteFileName);
+    if (doc) {
+        mergeEnvironment(doc);
+        return;
+    }
+
+    doc = Document::create(absoluteFileName);
+    doc->setRevision(m_revision);
+    doc->setEditorRevision(editorRevision);
+
+    QFileInfo info(absoluteFileName);
+    if (info.exists())
+        doc->setLastModified(info.lastModified());
+
+    Document::Ptr previousDoc = switchDocument(doc);
+
+    const QByteArray preprocessedCode = m_preprocess.run(absoluteFileName, contents);
+
+//    { QByteArray b(preprocessedCode); b.replace("\n", "<<<\n"); qDebug("Preprocessed code for \"%s\": [[%s]]", fileName.toUtf8().constData(), b.constData()); }
+
+    doc->setUtf8Source(preprocessedCode);
+    doc->keepSourceAndAST();
+    doc->tokenize();
+
+    m_snapshot.insert(doc);
+    m_todo.remove(absoluteFileName);
+
+    Process process(m_modelManager, doc, m_workingCopy);
+    process();
+
+    (void) switchDocument(previousDoc);
+}
+
+Document::Ptr CppPreprocessor::switchDocument(Document::Ptr doc)
+{
+    Document::Ptr previousDoc = m_currentDoc;
+    m_currentDoc = doc;
+    return previousDoc;
+}
diff --git a/src/plugins/cpptools/cpppreprocessor.h b/src/plugins/cpptools/cpppreprocessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..d931a880c4b7ae3af5233b54985b152b84e14618
--- /dev/null
+++ b/src/plugins/cpptools/cpppreprocessor.h
@@ -0,0 +1,91 @@
+#ifndef CPPPREPROCESSOR_H
+#define CPPPREPROCESSOR_H
+
+#include "cppmodelmanagerinterface.h"
+
+#include <cplusplus/PreprocessorEnvironment.h>
+#include <cplusplus/pp-engine.h>
+
+#include <QHash>
+#include <QPointer>
+
+namespace CppTools {
+namespace Internal {
+
+class CppModelManager;
+
+class CPPTOOLS_EXPORT CppPreprocessor: public CPlusPlus::Client
+{
+    Q_DISABLE_COPY(CppPreprocessor)
+
+public:
+    CppPreprocessor(QPointer<CppModelManager> modelManager, bool dumpFileNameWhileParsing = false);
+    virtual ~CppPreprocessor();
+
+    void setRevision(unsigned revision);
+    void setWorkingCopy(const CppTools::CppModelManagerInterface::WorkingCopy &workingCopy);
+    void setIncludePaths(const QStringList &includePaths);
+    void setFrameworkPaths(const QStringList &frameworkPaths);
+    void addFrameworkPath(const QString &frameworkPath);
+    void setProjectFiles(const QStringList &files);
+    void setTodo(const QStringList &files);
+
+    void run(const QString &fileName);
+    void removeFromCache(const QString &fileName);
+
+    void resetEnvironment();
+    static QString cleanPath(const QString &path);
+
+    const QSet<QString> &todo() const
+    { return m_todo; }
+
+    CppModelManager *modelManager() const
+    { return m_modelManager.data(); }
+
+protected:
+    CPlusPlus::Document::Ptr switchDocument(CPlusPlus::Document::Ptr doc);
+
+    void getFileContents(const QString &absoluteFilePath, QString *contents, unsigned *revision) const;
+    bool checkFile(const QString &absoluteFilePath) const;
+    QString resolveFile(const QString &fileName, IncludeType type);
+    QString resolveFile_helper(const QString &fileName, IncludeType type);
+
+    void mergeEnvironment(CPlusPlus::Document::Ptr doc);
+
+    virtual void macroAdded(const CPlusPlus::Macro &macro);
+    virtual void passedMacroDefinitionCheck(unsigned offset, unsigned line,
+                                            const CPlusPlus::Macro &macro);
+    virtual void failedMacroDefinitionCheck(unsigned offset, const CPlusPlus::ByteArrayRef &name);
+    virtual void notifyMacroReference(unsigned offset, unsigned line,
+                                      const CPlusPlus::Macro &macro);
+    virtual void startExpandingMacro(unsigned offset,
+                                     unsigned line,
+                                     const CPlusPlus::Macro &macro,
+                                     const QVector<CPlusPlus::MacroArgumentReference> &actuals);
+    virtual void stopExpandingMacro(unsigned offset, const CPlusPlus::Macro &macro);
+    virtual void markAsIncludeGuard(const QByteArray &macroName);
+    virtual void startSkippingBlocks(unsigned offset);
+    virtual void stopSkippingBlocks(unsigned offset);
+    virtual void sourceNeeded(unsigned line, const QString &fileName, IncludeType type);
+
+private:
+    CPlusPlus::Snapshot m_snapshot;
+    QPointer<CppModelManager> m_modelManager;
+    bool m_dumpFileNameWhileParsing;
+    CPlusPlus::Environment m_env;
+    CPlusPlus::Preprocessor m_preprocess;
+    QStringList m_includePaths;
+    CppTools::CppModelManagerInterface::WorkingCopy m_workingCopy;
+    QStringList m_frameworkPaths;
+    QSet<QString> m_included;
+    CPlusPlus::Document::Ptr m_currentDoc;
+    QSet<QString> m_todo;
+    QSet<QString> m_processed;
+    unsigned m_revision;
+    QHash<QString, QString> m_fileNameCache;
+};
+
+} // namespace Internal
+} // namespace CppTools
+
+#endif // CPPPREPROCESSOR_H
diff --git a/src/plugins/cpptools/cpptools.pro b/src/plugins/cpptools/cpptools.pro
index f77e869d68e56cc33282801d4746098c66abfeb7..efeff55f250509fa6a80bd491fd99d7ef9bcea04 100644
--- a/src/plugins/cpptools/cpptools.pro
+++ b/src/plugins/cpptools/cpptools.pro
@@ -44,7 +44,8 @@ HEADERS += completionsettingspage.h \
     cppindexingsupport.h \
     builtinindexingsupport.h \
     cpppointerdeclarationformatter.h \
-    cppprojectfile.h
+    cppprojectfile.h \
+    cpppreprocessor.h
 
 SOURCES += completionsettingspage.cpp \
     cppclassesfilter.cpp \
@@ -87,7 +88,8 @@ SOURCES += completionsettingspage.cpp \
     cppindexingsupport.cpp \
     builtinindexingsupport.cpp \
     cpppointerdeclarationformatter.cpp \
-    cppprojectfile.cpp
+    cppprojectfile.cpp \
+    cpppreprocessor.cpp
 
 FORMS += completionsettingspage.ui \
     cppfilesettingspage.ui \
diff --git a/src/plugins/cpptools/cpptools.qbs b/src/plugins/cpptools/cpptools.qbs
index a6a98539b8d4198920cbf46556010c2a7626103c..059a3dfc7e2525a8799fec7e79593c06bd97f9b2 100644
--- a/src/plugins/cpptools/cpptools.qbs
+++ b/src/plugins/cpptools/cpptools.qbs
@@ -105,7 +105,9 @@ QtcPlugin {
         "uicodecompletionsupport.cpp",
         "uicodecompletionsupport.h",
         "builtinindexingsupport.cpp",
-        "builtinindexingsupport.h"
+        "builtinindexingsupport.h",
+        "cpppreprocessor.cpp",
+        "cpppreprocessor.h"
     ]
 
     Group {
diff --git a/src/plugins/cpptools/cpptoolsplugin.cpp b/src/plugins/cpptools/cpptoolsplugin.cpp
index e8f1a46c84727a6a638dfdb10cd27003e198223f..7f70a37640c9cfb21620743049bfeba69d9c3fe5 100644
--- a/src/plugins/cpptools/cpptoolsplugin.cpp
+++ b/src/plugins/cpptools/cpptoolsplugin.cpp
@@ -27,8 +27,8 @@
 **
 ****************************************************************************/
 
+#include "cpptoolsconstants.h"
 #include "cpptoolsplugin.h"
-
 #include "cppfilesettingspage.h"
 #include "cppcodestylesettingspage.h"
 #include "cppclassesfilter.h"
diff --git a/src/plugins/cpptools/symbolsfindfilter.cpp b/src/plugins/cpptools/symbolsfindfilter.cpp
index fe4fc332c98657a445793322e105504cbd89f4cb..78c636674d0cf550a88b42eaf0555b43ed00962c 100644
--- a/src/plugins/cpptools/symbolsfindfilter.cpp
+++ b/src/plugins/cpptools/symbolsfindfilter.cpp
@@ -28,8 +28,8 @@
 ****************************************************************************/
 
 #include "symbolsfindfilter.h"
-
 #include "cppmodelmanager.h"
+#include "cpptoolsconstants.h"
 
 #include <coreplugin/icore.h>
 #include <coreplugin/progressmanager/futureprogress.h>