From 9a2114338432cfc883b29f514daa847205184833 Mon Sep 17 00:00:00 2001
From: Roberto Raggi <roberto.raggi@nokia.com>
Date: Wed, 30 Sep 2009 17:15:31 +0200
Subject: [PATCH] Implemented a simple(fast?) strategy to resolve macro
 references.

---
 src/libs/cplusplus/FastPreprocessor.cpp    | 62 ++++++++++++++++++++++
 src/libs/cplusplus/FastPreprocessor.h      | 19 +++++++
 src/plugins/cppeditor/cppeditor.cpp        |  9 +++-
 src/plugins/cpptools/cppfindreferences.cpp | 12 ++++-
 src/shared/cplusplus/Parser.cpp            |  4 ++
 5 files changed, 103 insertions(+), 3 deletions(-)

diff --git a/src/libs/cplusplus/FastPreprocessor.cpp b/src/libs/cplusplus/FastPreprocessor.cpp
index a0ad81521e0..1f5838f7a69 100644
--- a/src/libs/cplusplus/FastPreprocessor.cpp
+++ b/src/libs/cplusplus/FastPreprocessor.cpp
@@ -28,9 +28,71 @@
 **************************************************************************/
 
 #include "FastPreprocessor.h"
+#include <Literals.h>
+#include <TranslationUnit.h>
 
 using namespace CPlusPlus;
 
+FastMacroResolver::FastMacroResolver(const Snapshot &snapshot)
+    : _snapshot(snapshot)
+{ }
+
+bool FastMacroResolver::isMacro(TranslationUnit *unit, unsigned tokenIndex) const
+{
+    const Token &tk = unit->tokenAt(tokenIndex);
+    if (tk.isNot(T_IDENTIFIER))
+        return false;
+
+    Identifier *id = tk.identifier;
+    const QByteArray macroName = QByteArray::fromRawData(id->chars(), id->size());
+    const QString fileName = QString::fromUtf8(unit->fileName(), unit->fileNameLength());
+
+    bool done = false;
+    QSet<QString> processed;
+
+    if (isMacro_helper(macroName, fileName, &processed, &done))
+        return true;
+
+    return false;
+}
+
+bool FastMacroResolver::isMacro_helper(const QByteArray &macroName,
+                                       const QString &fileName,
+                                       QSet<QString> *processed,
+                                       bool *done) const
+{
+    if (processed->contains(fileName))
+        return false;
+
+    processed->insert(fileName);
+
+    if (Document::Ptr doc = _snapshot.value(fileName)) {
+        const QList<Macro> definedMacros = doc->definedMacros();
+
+        for (int i = definedMacros.size() - 1; i != -1; --i) {
+            const Macro &macro = definedMacros.at(i);
+
+            if (macro.name() == macroName) { // ### handle line numbers.
+                if (macro.isHidden()) {
+                    *done = true;
+                    return false;
+                }
+
+                return true;
+            }
+        }
+
+        foreach (const Document::Include &incl, doc->includes()) {
+            if (isMacro_helper(macroName, incl.fileName(), processed, done))
+                return true;
+            else if (*done)
+                return false;
+        }
+    }
+
+    return false;
+}
+
 FastPreprocessor::FastPreprocessor(const Snapshot &snapshot)
     : _snapshot(snapshot),
       _preproc(this, &_env)
diff --git a/src/libs/cplusplus/FastPreprocessor.h b/src/libs/cplusplus/FastPreprocessor.h
index 36f3685fc13..4db16643d89 100644
--- a/src/libs/cplusplus/FastPreprocessor.h
+++ b/src/libs/cplusplus/FastPreprocessor.h
@@ -34,11 +34,30 @@
 #include "CppDocument.h"
 #include "pp.h"
 
+#include <Control.h>
+
 #include <QtCore/QSet>
 #include <QtCore/QString>
 
 namespace CPlusPlus {
 
+class CPLUSPLUS_EXPORT FastMacroResolver: public MacroResolver
+{
+public:
+    FastMacroResolver(const Snapshot &snapshot);
+
+    virtual bool isMacro(TranslationUnit *unit, unsigned tokenIndex) const;
+
+private:
+    bool isMacro_helper(const QByteArray &macroName,
+                        const QString &fileName,
+                        QSet<QString> *processed,
+                        bool *done) const;
+
+private:
+    Snapshot _snapshot;
+};
+
 class CPLUSPLUS_EXPORT FastPreprocessor: public Client
 {
     Environment _env;
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index 9771328c5bb..9a3022c577c 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -57,6 +57,8 @@
 #include <cplusplus/TypeOfExpression.h>
 #include <cplusplus/MatchingText.h>
 #include <cplusplus/BackwardsScanner.h>
+#include <cplusplus/FastPreprocessor.h>
+
 #include <cpptools/cppmodelmanagerinterface.h>
 
 #include <coreplugin/icore.h>
@@ -2064,10 +2066,13 @@ SemanticInfo SemanticHighlighter::semanticInfo(const Source &source)
     if (!doc) {
         const QByteArray preprocessedCode = source.snapshot.preprocessedCode(source.code, source.fileName);
 
+        snapshot = source.snapshot;
         doc = source.snapshot.documentFromSource(preprocessedCode, source.fileName);
-        doc->check();
 
-        snapshot = source.snapshot;
+        FastMacroResolver fastMacroResolver(snapshot);
+        doc->control()->setMacroResolver(&fastMacroResolver);
+        doc->check();
+        doc->control()->setMacroResolver(0);
     }
 
     Control *control = doc->control();
diff --git a/src/plugins/cpptools/cppfindreferences.cpp b/src/plugins/cpptools/cppfindreferences.cpp
index bbee65f767c..ad9642f8bcb 100644
--- a/src/plugins/cpptools/cppfindreferences.cpp
+++ b/src/plugins/cpptools/cppfindreferences.cpp
@@ -52,6 +52,7 @@
 #include <cplusplus/ResolveExpression.h>
 #include <cplusplus/Overview.h>
 #include <cplusplus/TypeOfExpression.h>
+#include <cplusplus/FastPreprocessor.h>
 
 #include <QtCore/QTime>
 #include <QtCore/QtConcurrentRun>
@@ -425,6 +426,8 @@ static void find_helper(QFutureInterface<Core::Utils::FileSearchResult> &future,
 
     future.setProgressRange(0, files.size());
 
+    FastMacroResolver fastMacroResolver(snapshot);
+
     for (int i = 0; i < files.size(); ++i) {
         const QString &fileName = files.at(i);
         future.setProgressValueAndText(i, QFileInfo(fileName).fileName());
@@ -456,8 +459,15 @@ static void find_helper(QFutureInterface<Core::Utils::FileSearchResult> &future,
 
         Control *control = doc->control();
         if (Identifier *id = control->findIdentifier(symbolId->chars(), symbolId->size())) {
-            doc->check();
             TranslationUnit *unit = doc->translationUnit();
+            Control *control = doc->control();
+
+            control->setMacroResolver(&fastMacroResolver);
+            doc->parse();
+            control->setMacroResolver(0);
+
+            doc->check();
+
             Process process(doc, snapshot, &future);
             process(symbol, id, unit->ast());
         }
diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp
index 86f805b054a..45905829fc1 100644
--- a/src/shared/cplusplus/Parser.cpp
+++ b/src/shared/cplusplus/Parser.cpp
@@ -2561,6 +2561,10 @@ bool Parser::parseBuiltinTypeSpecifier(SpecifierAST *&node)
 bool Parser::parseSimpleDeclaration(DeclarationAST *&node,
                                     bool acceptStructDeclarator)
 {
+    if (LA() == T_IDENTIFIER && isMacro(cursor())) {
+        // printf("***** found macro reference `%s'\n", tok().identifier->chars());
+    }
+
     unsigned qt_invokable_token = 0;
     if (acceptStructDeclarator && (LA() == T_Q_SIGNAL || LA() == T_Q_SLOT))
         qt_invokable_token = consumeToken();
-- 
GitLab