diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp
index 9faabe29b13fde6f762878112c520c11bf393753..675cf6edf91a6a95ae683e2084ac0cc3be241c68 100644
--- a/src/libs/cplusplus/CppDocument.cpp
+++ b/src/libs/cplusplus/CppDocument.cpp
@@ -44,6 +44,11 @@
 #include <QtCore/QBitArray>
 #include <QtCore/QtDebug>
 
+/*!
+    \namespace CPlusPlus
+    The namespace for C++ related tools.
+*/
+
 using namespace CPlusPlus;
 
 namespace {
@@ -101,6 +106,7 @@ private:
 
 } // anonymous namespace
 
+
 Document::Document(const QString &fileName)
     : _fileName(fileName),
       _globalNamespace(0),
@@ -166,9 +172,10 @@ void Document::appendMacro(const Macro &macro)
 }
 
 void Document::addMacroUse(const Macro &macro, unsigned offset, unsigned length,
-                           const QVector<MacroArgumentReference> &actuals)
+                           const QVector<MacroArgumentReference> &actuals, bool inCondition)
 {
     MacroUse use(macro, offset, offset + length);
+    use.setInCondition(inCondition);
 
     foreach (const MacroArgumentReference &actual, actuals) {
         const Block arg(actual.position(), actual.position() + actual.length());
@@ -179,6 +186,60 @@ void Document::addMacroUse(const Macro &macro, unsigned offset, unsigned length,
     _macroUses.append(use);
 }
 
+void Document::addUndefinedMacroUse(const QByteArray &name, unsigned offset)
+{
+    QByteArray copy(name.data(), name.size());
+    UndefinedMacroUse use(copy, offset);
+    _undefinedMacroUses.append(use);
+}
+
+/*!
+    \class Document::MacroUse
+    \brief Represents the usage of a macro in a \l {Document}.
+    \sa Document::UndefinedMacroUse
+*/
+
+/*!
+    \class Document::UndefinedMacroUse
+    \brief Represents a macro that was looked up, but not found.
+
+    Holds data about the reference to a macro in an \tt{#ifdef} or \tt{#ifndef}
+    or argument to the \tt{defined} operator inside an \tt{#if} or \tt{#elif} that does
+    not exist.
+
+    \sa Document::undefinedMacroUses(), Document::MacroUse, Macro
+*/
+
+/*!
+    \fn QByteArray Document::UndefinedMacroUse::name() const
+
+    Returns the name of the macro that was not found.
+*/
+
+/*!
+    \fn QList<UndefinedMacroUse> Document::undefinedMacroUses() const
+
+    Returns a list of referenced but undefined macros.
+
+    \sa Document::macroUses(), Document::definedMacros(), Macro
+*/
+
+/*!
+    \fn QList<MacroUse> Document::macroUses() const
+
+    Returns a list of macros used.
+
+    \sa Document::undefinedMacroUses(), Document::definedMacros(), Macro
+*/
+
+/*!
+    \fn QList<Macro> Document::definedMacros() const
+
+    Returns the list of macros defined.
+
+    \sa Document::macroUses(), Document::undefinedMacroUses()
+*/
+
 TranslationUnit *Document::translationUnit() const
 {
     return _translationUnit;
diff --git a/src/libs/cplusplus/CppDocument.h b/src/libs/cplusplus/CppDocument.h
index 7308e04e6007db324fd25ff21135ef7f760cb609..ca15bd1986d761cfa29b215fe6940638b296f2de 100644
--- a/src/libs/cplusplus/CppDocument.h
+++ b/src/libs/cplusplus/CppDocument.h
@@ -70,7 +70,8 @@ public:
 
     void appendMacro(const Macro &macro);
     void addMacroUse(const Macro &macro, unsigned offset, unsigned length,
-                     const QVector<MacroArgumentReference> &range);
+                     const QVector<MacroArgumentReference> &range, bool inCondition);
+    void addUndefinedMacroUse(const QByteArray &name, unsigned offset);
 
     Control *control() const;
     TranslationUnit *translationUnit() const;
@@ -220,13 +221,15 @@ public:
     class MacroUse: public Block {
         Macro _macro;
         QVector<Block> _arguments;
+        bool _inCondition;
 
     public:
         inline MacroUse(const Macro &macro,
                         unsigned begin = 0,
                         unsigned end = 0)
             : Block(begin, end),
-              _macro(macro)
+              _macro(macro),
+              _inCondition(false)
         { }
 
         const Macro &macro() const
@@ -238,11 +241,37 @@ public:
         QVector<Block> arguments() const
         { return _arguments; }
 
+        bool isInCondition() const
+        { return _inCondition; }
+
+    private:
         void setArguments(const QVector<Block> &arguments)
         { _arguments = arguments; }
 
         void addArgument(const Block &block)
         { _arguments.append(block); }
+
+        void setInCondition(bool set)
+        { _inCondition = set; }
+
+        friend class Document;
+    };
+
+    class UndefinedMacroUse: public Block {
+        QByteArray _name;
+
+    public:
+        inline UndefinedMacroUse(
+                const QByteArray &name,
+                unsigned begin = 0)
+            : Block(begin, begin + name.length()),
+              _name(name)
+        { }
+
+        QByteArray name() const
+        {
+            return _name;
+        }
     };
 
     QList<Include> includes() const
@@ -254,6 +283,9 @@ public:
     QList<MacroUse> macroUses() const
     { return _macroUses; }
 
+    QList<UndefinedMacroUse> undefinedMacroUses() const
+    { return _undefinedMacroUses; }
+
 private:
     Symbol *findSymbolAt(unsigned line, unsigned column, Scope *scope) const;
 
@@ -267,6 +299,7 @@ private:
     QList<Macro> _definedMacros;
     QList<Block> _skippedBlocks;
     QList<MacroUse> _macroUses;
+    QList<UndefinedMacroUse> _undefinedMacroUses;
     QByteArray _source;
     unsigned _revision;
 
diff --git a/src/libs/cplusplus/FastPreprocessor.h b/src/libs/cplusplus/FastPreprocessor.h
index 0d82d54253f69175a6126de19abf227fef5c73f6..36f3685fc13915d42b742f4a6240336050680fd0 100644
--- a/src/libs/cplusplus/FastPreprocessor.h
+++ b/src/libs/cplusplus/FastPreprocessor.h
@@ -58,9 +58,13 @@ public:
 
     virtual void macroAdded(const Macro &) {}
 
+    virtual void passedMacroDefinitionCheck(unsigned, const Macro &) {}
+    virtual void failedMacroDefinitionCheck(unsigned, const QByteArray &) {}
+
     virtual void startExpandingMacro(unsigned,
                                      const Macro &,
                                      const QByteArray &,
+                                     bool,
                                      const QVector<MacroArgumentReference> &) {}
 
     virtual void stopExpandingMacro(unsigned, const Macro &) {}
diff --git a/src/libs/cplusplus/PreprocessorClient.cpp b/src/libs/cplusplus/PreprocessorClient.cpp
index 6fe1b2a75b9eadf00c2e5fbc5e89ca24c44e4b0b..5b57baa7b2eb0a65863f5f70d42ab86983b73ba9 100644
--- a/src/libs/cplusplus/PreprocessorClient.cpp
+++ b/src/libs/cplusplus/PreprocessorClient.cpp
@@ -31,6 +31,44 @@
 
 using namespace CPlusPlus;
 
+/*!
+    \class Client
+    \brief A notification interface for for C++ preprocessor.
+*/
+
+/*!
+    \fn void Client::macroAdded(const Macro &macro)
+
+    Called whenever a new macro is defined.
+*/
+
+/*!
+    \fn void Client::passedMacroDefinitionCheck(unsigned offset, const Macro &macro)
+
+    Called when the preprocessor checks whether a macro is defined or not and the
+    result is positive.
+
+    \sa failedMacroDefinitionCheck()
+*/
+
+/*!
+    \fn void Client::failedMacroDefinitionCheck(unsigned offset, const QByteArray &name)
+
+    Called when the preprocessor checks whether a macro is defined or not and the
+    result is negative.
+
+    \sa passedMacroDefinitionCheck()
+*/
+
+/*!
+    \fn void Client::startExpandingMacro(unsigned offset, const Macro &macro, const QByteArray &originalText, bool inCondition = false, const QVector<MacroArgumentReference> &actuals = QVector<MacroArgumentReference>())
+    
+    Called when starting to expand a macro. The parameter \a inCondition indicates whether the
+    expansion is happening inside a preprocessor conditional.
+    
+    \sa stopExpandingMacro()
+*/
+
 Client::Client()
 { }
 
diff --git a/src/libs/cplusplus/PreprocessorClient.h b/src/libs/cplusplus/PreprocessorClient.h
index 84cb0b73ac372c0d980f8ab4eeee512d5d74aa21..d89ce71355d6bd17152c152d293a555b0d8fa562 100644
--- a/src/libs/cplusplus/PreprocessorClient.h
+++ b/src/libs/cplusplus/PreprocessorClient.h
@@ -75,12 +75,14 @@ public:
   virtual ~Client();
 
   virtual void macroAdded(const Macro &macro) = 0;
-  virtual void sourceNeeded(QString &fileName, IncludeType mode,
-                            unsigned line) = 0; // ### FIX the signature.
+
+  virtual void passedMacroDefinitionCheck(unsigned offset, const Macro &macro) = 0;
+  virtual void failedMacroDefinitionCheck(unsigned offset, const QByteArray &name) = 0;
 
   virtual void startExpandingMacro(unsigned offset,
                                    const Macro &macro,
                                    const QByteArray &originalText,
+                                   bool inCondition = false,
                                    const QVector<MacroArgumentReference> &actuals
                                             = QVector<MacroArgumentReference>()) = 0;
 
@@ -89,6 +91,9 @@ public:
 
   virtual void startSkippingBlocks(unsigned offset) = 0;
   virtual void stopSkippingBlocks(unsigned offset) = 0;
+
+  virtual void sourceNeeded(QString &fileName, IncludeType mode,
+                            unsigned line) = 0; // ### FIX the signature.
 };
 
 } // namespace CPlusPlus
diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp
index 347f4999d26d2eb2e8d1bf62138552ec802ff726..dcb6d4932223f7df5b1adb2da49583e1a2932e9b 100644
--- a/src/libs/cplusplus/pp-engine.cpp
+++ b/src/libs/cplusplus/pp-engine.cpp
@@ -138,6 +138,18 @@ using namespace CPlusPlus;
 
 namespace {
 
+bool isMacroDefined(QByteArray name, unsigned offset, Environment *env, Client *client)
+{
+    Macro *m = env->resolve(name);
+    if (client) {
+        if (m)
+            client->passedMacroDefinitionCheck(offset, *m);
+        else
+            client->failedMacroDefinitionCheck(offset, name);
+    }
+    return m != 0;
+}
+
 class RangeLexer
 {
     const Token *first;
@@ -193,8 +205,8 @@ class ExpressionEvaluator
     void operator = (const ExpressionEvaluator &other);
 
 public:
-    ExpressionEvaluator(Environment *env)
-        : env(env), _lex(0)
+    ExpressionEvaluator(Client *client, Environment *env)
+        : client(client), env(env), _lex(0)
     { }
 
     Value operator()(const Token *firstToken, const Token *lastToken,
@@ -255,13 +267,13 @@ protected:
         } else if (isTokenDefined()) {
             ++(*_lex);
             if ((*_lex)->is(T_IDENTIFIER)) {
-                _value.set_long(env->resolve(tokenSpell()) != 0);
+                _value.set_long(isMacroDefined(tokenSpell(), (*_lex)->offset, env, client));
                 ++(*_lex);
                 return true;
             } else if ((*_lex)->is(T_LPAREN)) {
                 ++(*_lex);
                 if ((*_lex)->is(T_IDENTIFIER)) {
-                    _value.set_long(env->resolve(tokenSpell()) != 0);
+                    _value.set_long(isMacroDefined(tokenSpell(), (*_lex)->offset, env, client));
                     ++(*_lex);
                     if ((*_lex)->is(T_RPAREN)) {
                         ++(*_lex);
@@ -519,6 +531,7 @@ protected:
     }
 
 private:
+    Client *client;
     Environment *env;
     QByteArray source;
     RangeLexer *_lex;
@@ -983,7 +996,7 @@ void Preprocessor::expandObjectLikeMacro(TokenIterator identifierToken,
 {
     if (client)
         client->startExpandingMacro(identifierToken->offset,
-                                    *m, spell);
+                                    *m, spell, false);
 
     m->setHidden(true);
     expand(m->definition(), result);
@@ -1007,7 +1020,7 @@ void Preprocessor::expandFunctionLikeMacro(TokenIterator identifierToken,
                                         endOfText - beginOfText);
 
         client->startExpandingMacro(identifierToken->offset,
-                                    *m, text, actuals);
+                                    *m, text, false, actuals);
     }
 
     const bool was = markGeneratedTokens(true, identifierToken);
@@ -1253,7 +1266,7 @@ void Preprocessor::processIf(TokenIterator firstToken, TokenIterator lastToken)
         const char *first = startOfToken(*tk);
         const char *last = startOfToken(*lastToken);
 
-        MacroExpander expandCondition (env);
+        MacroExpander expandCondition (env, 0, client, tk.dot()->offset);
         QByteArray condition;
         condition.reserve(256);
         expandCondition(first, last, &condition);
@@ -1297,7 +1310,7 @@ void Preprocessor::processElif(TokenIterator firstToken, TokenIterator lastToken
         const char *first = startOfToken(*tk);
         const char *last = startOfToken(*lastToken);
 
-        MacroExpander expandCondition (env);
+        MacroExpander expandCondition (env, 0, client, tk.dot()->offset);
         QByteArray condition;
         condition.reserve(256);
         expandCondition(first, last, &condition);
@@ -1338,7 +1351,7 @@ void Preprocessor::processIfdef(bool checkUndefined,
     if (testIfLevel()) {
         if (tk->is(T_IDENTIFIER)) {
             const QByteArray macroName = tokenSpell(*tk);
-            bool value = env->resolve(macroName) != 0 || env->isBuiltinMacro(macroName);
+            bool value = isMacroDefined(macroName, tk->offset, env, client) || env->isBuiltinMacro(macroName);
 
             if (checkUndefined)
                 value = ! value;
@@ -1437,7 +1450,7 @@ int Preprocessor::skipping() const
 Value Preprocessor::evalExpression(TokenIterator firstToken, TokenIterator lastToken,
                                    const QByteArray &source) const
 {
-    ExpressionEvaluator eval(env);
+    ExpressionEvaluator eval(client, env);
     const Value result = eval(firstToken, lastToken, source);
     return result;
 }
diff --git a/src/libs/cplusplus/pp-macro-expander.cpp b/src/libs/cplusplus/pp-macro-expander.cpp
index 4902158c761e00afc10c28f93a4a5e391e1538b6..42be634562d445eafebffe413820cd8c969d2300 100644
--- a/src/libs/cplusplus/pp-macro-expander.cpp
+++ b/src/libs/cplusplus/pp-macro-expander.cpp
@@ -66,9 +66,11 @@ inline static bool comment_p (const char *__first, const char *__last)
     return (*__first == '/' || *__first == '*');
 }
 
-MacroExpander::MacroExpander(Environment *env, pp_frame *frame)
+MacroExpander::MacroExpander(Environment *env, pp_frame *frame, Client *client, unsigned start_offset)
     : env(env),
       frame(frame),
+      client(client),
+      start_offset(start_offset),
       lines(0)
 { }
 
@@ -97,6 +99,7 @@ const char *MacroExpander::operator()(const char *first, const char *last,
 const char *MacroExpander::expand(const char *__first, const char *__last,
                                   QByteArray *__result)
 {
+    const char *start = __first;
     __first = skip_blanks (__first, __last);
     lines = skip_blanks.lines;
 
@@ -284,6 +287,9 @@ const char *MacroExpander::expand(const char *__first, const char *__last,
 
                 if (! macro->definition().isEmpty())
                 {
+                    if (client)
+                        client->startExpandingMacro(start_offset + (name_begin-start), *macro, fast_name, true);
+
                     macro->setHidden(true);
 
                     QByteArray __tmp;
@@ -310,6 +316,9 @@ const char *MacroExpander::expand(const char *__first, const char *__last,
                     }
 
                     macro->setHidden(false);
+
+                    if (client)
+                        client->stopExpandingMacro(start_offset + (name_begin-start), *macro);
                 }
 
                 if (! m)
@@ -330,6 +339,7 @@ const char *MacroExpander::expand(const char *__first, const char *__last,
             }
 
             QVector<QByteArray> actuals;
+            QVector<MacroArgumentReference> actuals_ref;
             actuals.reserve (5);
             ++arg_it; // skip '('
 
@@ -338,6 +348,7 @@ const char *MacroExpander::expand(const char *__first, const char *__last,
             const char *arg_end = skip_argument_variadics (actuals, macro, arg_it, __last);
             if (arg_it != arg_end)
             {
+                actuals_ref.append(MacroArgumentReference(start_offset + (arg_it-start), arg_end - arg_it));
                 const QByteArray actual (arg_it, arg_end - arg_it);
                 QByteArray expanded;
                 expand_actual (actual.constBegin (), actual.constEnd (), &expanded);
@@ -350,6 +361,7 @@ const char *MacroExpander::expand(const char *__first, const char *__last,
                 ++arg_it; // skip ','
 
                 arg_end = skip_argument_variadics (actuals, macro, arg_it, __last);
+                actuals_ref.append(MacroArgumentReference(start_offset + (arg_it-start), arg_end - arg_it));
                 const QByteArray actual (arg_it, arg_end - arg_it);
                 QByteArray expanded;
                 expand_actual (actual.constBegin (), actual.constEnd (), &expanded);
@@ -363,11 +375,17 @@ const char *MacroExpander::expand(const char *__first, const char *__last,
             ++arg_it; // skip ')'
             __first = arg_it;
 
+            if (client)
+                client->startExpandingMacro(start_offset + (name_begin-start), *macro, fast_name, true, actuals_ref);
+
             pp_frame frame (macro, actuals);
             MacroExpander expand_macro (env, &frame);
             macro->setHidden(true);
             expand_macro (macro->definition(), __result);
             macro->setHidden(false);
+
+            if (client)
+                client->stopExpandingMacro(start_offset + (name_begin-start), *macro);
         }
         else
             __result->append(*__first++);
diff --git a/src/libs/cplusplus/pp-macro-expander.h b/src/libs/cplusplus/pp-macro-expander.h
index f566ca809bb0488d4ffc109a165b094fc8a1c5a2..4f8730d2db8e92f0a5cd90a322bdbd6129774c8a 100644
--- a/src/libs/cplusplus/pp-macro-expander.h
+++ b/src/libs/cplusplus/pp-macro-expander.h
@@ -56,6 +56,7 @@
 namespace CPlusPlus {
 
 class Environment;
+class Client;
 
 struct pp_frame;
 
@@ -63,6 +64,8 @@ class MacroExpander
 {
     Environment *env;
     pp_frame *frame;
+    Client *client;
+    unsigned start_offset;
 
     pp_skip_number skip_number;
     pp_skip_identifier skip_identifier;
@@ -76,7 +79,7 @@ class MacroExpander
     const QByteArray *resolve_formal(const QByteArray &name);
 
 public:
-    MacroExpander(Environment *env, pp_frame *frame = 0);
+    MacroExpander(Environment *env, pp_frame *frame = 0, Client *client = 0, unsigned start_offset = 0);
 
     const char *operator()(const char *first, const char *last,
                              QByteArray *result);
diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp
index 5d76824ff9b017a9e574a006ac6a5066389a80dd..6a859d16cc7bc04f9991f1f15e2745015e81bb24 100644
--- a/src/plugins/cpptools/cppmodelmanager.cpp
+++ b/src/plugins/cpptools/cppmodelmanager.cpp
@@ -196,9 +196,12 @@ protected:
     void mergeEnvironment(CPlusPlus::Document::Ptr doc);
 
     virtual void macroAdded(const Macro &macro);
+    virtual void passedMacroDefinitionCheck(unsigned offset, const Macro &macro);
+    virtual void failedMacroDefinitionCheck(unsigned offset, const QByteArray &name);
     virtual void startExpandingMacro(unsigned offset,
                                      const Macro &macro,
                                      const QByteArray &originalText,
+                                     bool inCondition,
                                      const QVector<MacroArgumentReference> &actuals);
     virtual void stopExpandingMacro(unsigned offset, const Macro &macro);
     virtual void startSkippingBlocks(unsigned offset);
@@ -446,16 +449,34 @@ void CppPreprocessor::macroAdded(const Macro &macro)
     m_currentDoc->appendMacro(macro);
 }
 
+void CppPreprocessor::passedMacroDefinitionCheck(unsigned offset, const Macro &macro)
+{
+    if (! m_currentDoc)
+        return;
+
+    m_currentDoc->addMacroUse(macro, offset, macro.name().length(),
+                              QVector<MacroArgumentReference>(), true);
+}
+
+void CppPreprocessor::failedMacroDefinitionCheck(unsigned offset, const QByteArray &name)
+{
+    if (! m_currentDoc)
+        return;
+
+    m_currentDoc->addUndefinedMacroUse(name, offset);
+}
+
 void CppPreprocessor::startExpandingMacro(unsigned offset,
                                           const Macro &macro,
                                           const QByteArray &originalText,
+                                          bool inCondition,
                                           const QVector<MacroArgumentReference> &actuals)
 {
     if (! m_currentDoc)
         return;
 
-    //qDebug() << "start expanding:" << macro.name << "text:" << originalText;
-    m_currentDoc->addMacroUse(macro, offset, originalText.length(), actuals);
+    //qDebug() << "start expanding:" << macro.name() << "text:" << originalText;
+    m_currentDoc->addMacroUse(macro, offset, originalText.length(), actuals, inCondition);
 }
 
 void CppPreprocessor::stopExpandingMacro(unsigned, const Macro &)