diff options
author | Ivan Donchevskii <ivan.donchevskii@qt.io> | 2019-01-10 14:44:56 +0100 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@qt.io> | 2019-01-17 08:52:40 +0000 |
commit | 645bbf5dd6f96835f289aca1b628370813aac692 (patch) | |
tree | 37651c4e93ac8b1d4df24a2481124cd88461817f /src | |
parent | 66dc5e971399fbd7bf696344698b5bd3fb05b819 (diff) |
CPlusPlus: Block function-like macro name for arguments expansion
Arguments of funstion-like macro may contain the name of this
macro. The attempt to expand it results into infinite recursion.
Patch solves that by saving the macro name until the arguments
are collected to determine that it should not be expanded.
Fixes: QTCREATORBUG-21642
Change-Id: Iafb404ecd3959a2f1011c12c1c3f1c0c54ed3547
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/libs/cplusplus/pp-engine.cpp | 34 | ||||
-rw-r--r-- | src/libs/cplusplus/pp-engine.h | 3 |
2 files changed, 26 insertions, 11 deletions
diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index 5ee8298a72..0050a2fd84 100644 --- a/src/libs/cplusplus/pp-engine.cpp +++ b/src/libs/cplusplus/pp-engine.cpp @@ -52,6 +52,7 @@ #include <cplusplus/Literals.h> #include <cplusplus/cppassert.h> +#include <utils/executeondestruction.h> #include <utils/scopedswap.h> #include <QDebug> @@ -161,6 +162,7 @@ namespace Internal { struct TokenBuffer { std::deque<PPToken> tokens; + std::vector<QByteArray> blockedMacroNames; const Macro *macro; TokenBuffer *next; @@ -172,10 +174,14 @@ struct TokenBuffer if (!macro) return false; - for (const TokenBuffer *it = this; it; it = it->next) - if (it->macro) - if (it->macro == macro || (it->macro->name() == macro->name())) - return true; + for (const TokenBuffer *it = this; it; it = it->next) { + if (it->macro && (it->macro == macro || it->macro->name() == macro->name())) + return true; + } + for (const QByteArray &blockedMacroName : blockedMacroNames) { + if (macro->name() == blockedMacroName) + return true; + } return false; } }; @@ -956,9 +962,7 @@ bool Preprocessor::handleIdentifier(PPToken *tk) Macro *macro = m_env->resolve(macroNameRef); if (!macro - || (tk->expanded() - && m_state.m_tokenBuffer - && m_state.m_tokenBuffer->isBlocked(macro))) { + || (tk->expanded() && m_state.m_tokenBuffer && m_state.m_tokenBuffer->isBlocked(macro))) { return false; } // qDebug() << "expanding" << macro->name() << "on line" << tk->lineno; @@ -991,7 +995,7 @@ bool Preprocessor::handleIdentifier(PPToken *tk) // Collect individual tokens that form the macro arguments. QVector<QVector<PPToken> > allArgTks; - bool hasArgs = collectActualArguments(tk, &allArgTks); + bool hasArgs = collectActualArguments(tk, &allArgTks, macro->name()); // Check whether collecting arguments failed due to a previously added marker // that goot nested in a sequence of expansions. If so, store it and try again. @@ -1001,7 +1005,7 @@ bool Preprocessor::handleIdentifier(PPToken *tk) && (m_state.m_expansionStatus == Expanding || m_state.m_expansionStatus == ReadyForExpansion)) { oldMarkerTk = *tk; - hasArgs = collectActualArguments(tk, &allArgTks); + hasArgs = collectActualArguments(tk, &allArgTks, macro->name()); } // Check for matching parameter/argument count. @@ -1498,11 +1502,21 @@ bool Preprocessor::consumeComments(PPToken *tk) return tk->isNot(T_EOF_SYMBOL); } -bool Preprocessor::collectActualArguments(PPToken *tk, QVector<QVector<PPToken> > *actuals) +bool Preprocessor::collectActualArguments(PPToken *tk, QVector<QVector<PPToken> > *actuals, + const QByteArray &parentMacroName) { Q_ASSERT(tk); Q_ASSERT(actuals); + ExecuteOnDestruction removeBlockedName; + if (m_state.m_tokenBuffer) { + removeBlockedName.reset([this] { + if (m_state.m_tokenBuffer && !m_state.m_tokenBuffer->blockedMacroNames.empty()) + m_state.m_tokenBuffer->blockedMacroNames.pop_back(); + }); + m_state.m_tokenBuffer->blockedMacroNames.push_back(parentMacroName); + } + lex(tk); // consume the identifier bool lastCommentIsCpp = false; diff --git a/src/libs/cplusplus/pp-engine.h b/src/libs/cplusplus/pp-engine.h index 19935b2c7d..fb9cdda2b2 100644 --- a/src/libs/cplusplus/pp-engine.h +++ b/src/libs/cplusplus/pp-engine.h @@ -220,7 +220,8 @@ private: bool scanComment(PPToken *tk); bool consumeComments(PPToken *tk); - bool collectActualArguments(PPToken *tk, QVector<QVector<PPToken> > *actuals); + bool collectActualArguments(PPToken *tk, QVector<QVector<PPToken> > *actuals, + const QByteArray &parentMacroName); void scanActualArgument(PPToken *tk, QVector<PPToken> *tokens); void handlePreprocessorDirective(PPToken *tk); |