summaryrefslogtreecommitdiffstats
path: root/src/tools
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@nokia.com>2012-09-07 15:13:03 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2012-09-25 00:08:16 +0200
commit34a3b63dc7d3b09342647537d378f5a55d0c81f0 (patch)
treeb467550408d47d40c40e640ccb20f1cc779cb202 /src/tools
parent0077b1e3a07cc3ea49fde3f938d59b44579f043d (diff)
Correctly expand macros without arguments in moc
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>
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/moc/preprocessor.cpp65
-rw-r--r--src/tools/moc/preprocessor.h1
2 files changed, 51 insertions, 15 deletions
diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp
index dc5136d4a6..4d4b571742 100644
--- a/src/tools/moc/preprocessor.cpp
+++ b/src/tools/moc/preprocessor.cpp
@@ -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
diff --git a/src/tools/moc/preprocessor.h b/src/tools/moc/preprocessor.h
index 0961f4780d..70121c2102 100644
--- a/src/tools/moc/preprocessor.h
+++ b/src/tools/moc/preprocessor.h
@@ -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();