Correctly expand macros without arguments in moc
authorLars Knoll <lars.knoll@nokia.com>
Fri, 7 Sep 2012 13:13:03 +0000 (15:13 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Mon, 24 Sep 2012 22:08:16 +0000 (00:08 +0200)
This helps e.g. cases where a namespace is defined
through a macro and moc doesn't see it at all.

Expanding macros with arguments is significantly more
work, and should happen in a separate commit.

Change-Id: Ic8d0443d06fab2ed343115d8c43022f2c67ec3cd
Reviewed-by: Qt Doc Bot <qt_docbot@qt-project.org>
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
src/tools/moc/preprocessor.cpp
src/tools/moc/preprocessor.h

index dc5136d..4d4b571 100644 (file)
@@ -157,14 +157,14 @@ bool Preprocessor::skipBranch()
 }
 
 
-enum TokenizeMode { TokenizeCpp, TokenizePreprocessor, PreparePreprocessorStatement, TokenizePreprocessorStatement, TokenizeInclude };
+enum TokenizeMode { TokenizeCpp, TokenizePreprocessor, PreparePreprocessorStatement, TokenizePreprocessorStatement, TokenizeInclude, PrepareDefine, TokenizeDefine };
 static Symbols tokenize(const QByteArray &input, int lineNum = 1, TokenizeMode mode = TokenizeCpp)
 {
     Symbols symbols;
     const char *begin = input.constData();
     const char *data = begin;
     while (*data) {
-        if (mode == TokenizeCpp) {
+        if (mode == TokenizeCpp || mode == TokenizeDefine) {
             int column = 0;
 
             const char *lexem = data;
@@ -278,6 +278,11 @@ static Symbols tokenize(const QByteArray &input, int lineNum = 1, TokenizeMode m
                     break;
                 case NEWLINE:
                     ++lineNum;
+                    if (mode == TokenizeDefine) {
+                        mode = TokenizeCpp;
+                        // emit the newline token
+                        break;
+                    }
                     continue;
                 case BACKSLASH:
                 {
@@ -375,6 +380,9 @@ static Symbols tokenize(const QByteArray &input, int lineNum = 1, TokenizeMode m
             case NOTOKEN:
                 ++data;
                 break;
+            case PP_DEFINE:
+                mode = PrepareDefine;
+                break;
             case PP_IFDEF:
                 symbols += Symbol(lineNum, PP_IF);
                 symbols += Symbol(lineNum, PP_DEFINED);
@@ -441,6 +449,16 @@ static Symbols tokenize(const QByteArray &input, int lineNum = 1, TokenizeMode m
                 while (is_ident_char(*data))
                     ++data;
                 token = PP_IDENTIFIER;
+
+                if (mode == PrepareDefine) {
+                    symbols += Symbol(lineNum, token, input, lexem-begin, data-lexem);
+                    // make sure we explicitly add the whitespace here, so we can distinguish
+                    // correctly between regular and function macros
+                    if (is_space(*data))
+                        symbols += Symbol(lineNum, WHITESPACE);
+                    mode = TokenizeDefine;
+                    continue;
+                }
                 break;
             case PP_C_COMMENT:
                 if (*data) {
@@ -510,6 +528,32 @@ static Symbols tokenize(const QByteArray &input, int lineNum = 1, TokenizeMode m
     return symbols;
 }
 
+void Preprocessor::macroExpandIdentifier(const Symbol &s, Symbols &preprocessed, MacroSafeSet safeset)
+{
+    // not a macro
+    if (!macros.contains(s)) {
+        preprocessed += s;
+        return;
+    }
+
+    Symbols expanded = macros.value(s).symbols;
+
+    // don't expand macros with arguments for now
+    if (expanded.size() && expanded.at(0).token == PP_LPAREN) {
+        preprocessed += s;
+        return;
+    }
+
+    for (int i = 0; i < expanded.size(); ++i) {
+        expanded[i].lineNum = s.lineNum;
+        if (expanded.at(i).token == PP_IDENTIFIER)
+            macroExpandIdentifier(expanded.at(i), preprocessed, safeset);
+        else
+            preprocessed += expanded.at(i);
+    }
+}
+
+
 void Preprocessor::substituteMacro(const MacroName &macro, Symbols &substituted, MacroSafeSet safeset)
 {
     Symbols saveSymbols = symbols;
@@ -878,20 +922,11 @@ void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed)
             macros.remove(name);
             continue;
         }
-        case PP_IDENTIFIER:
-        {
-//             if (macros.contains(symbol()))
-//                 ;
+        case PP_IDENTIFIER: {
+            // substitute macros
+            macroExpandIdentifier(symbol(), preprocessed);
+            continue;
         }
-            // we _could_ easily substitute macros by the following
-            // four lines, but we choose not to.
-            /*
-            if (macros.contains(sym.lexem())) {
-                preprocessed += substitute(macros, symbols, i);
-                continue;
-            }
-            */
-            break;
         case PP_HASH:
             until(PP_NEWLINE);
             continue; // skip unknown preprocessor statement
index 0961f47..70121c2 100644 (file)
@@ -81,6 +81,7 @@ public:
 
     void substituteMacro(const MacroName &macro, Symbols &substituted, MacroSafeSet safeset = MacroSafeSet());
     void substituteUntilNewline(Symbols &substituted, MacroSafeSet safeset = MacroSafeSet());
+    void macroExpandIdentifier(const Symbol &s, Symbols &preprocessed, MacroSafeSet safeset = MacroSafeSet());
 
     int evaluateCondition();