diff --git a/src/libs/cplusplus/PPToken.cpp b/src/libs/cplusplus/PPToken.cpp index 2f352fa1096..ff3996aba9d 100644 --- a/src/libs/cplusplus/PPToken.cpp +++ b/src/libs/cplusplus/PPToken.cpp @@ -54,6 +54,7 @@ void PPToken::squeezeSource() if (hasSource()) { m_src = m_src.mid(byteOffset, f.bytes); m_src.squeeze(); + m_originalOffset = byteOffset; byteOffset = 0; utf16charOffset = 0; } diff --git a/src/libs/cplusplus/PPToken.h b/src/libs/cplusplus/PPToken.h index 8eb8b26ab6c..af31dec861c 100644 --- a/src/libs/cplusplus/PPToken.h +++ b/src/libs/cplusplus/PPToken.h @@ -129,8 +129,19 @@ public: ByteArrayRef asByteArrayRef() const { return ByteArrayRef(&m_src, byteOffset, bytes()); } + unsigned originalOffset() const + { return m_originalOffset != -1 ? m_originalOffset : byteOffset; } + private: QByteArray m_src; + + // TODO: We may or may not be able to get rid of this member. In order to find out, + // all code calling this class' accessors (including the parent class' + // bytes* and utf16* functions) has to be looked at. Essentially, it boils + // down to whether there are contexts where an object of this class is used + // and the original "global" string is no longer available. (If not, then the + // m_src member would also not be needed.) + int m_originalOffset = -1; }; } // namespace Internal diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index d1f2d3eaf5b..e23049f220c 100644 --- a/src/libs/cplusplus/pp-engine.cpp +++ b/src/libs/cplusplus/pp-engine.cpp @@ -1856,7 +1856,7 @@ void Preprocessor::handleDefineDirective(PPToken *tk) QByteArray Preprocessor::expand(PPToken *tk, PPToken *lastConditionToken) { unsigned line = tk->lineno; - unsigned bytesBegin = tk->bytesBegin(); + unsigned bytesBegin = tk->originalOffset(); unsigned utf16charsBegin = tk->utf16charsBegin(); PPToken lastTk; while (isContinuationToken(*tk)) { diff --git a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp index 005ea5c1fad..6801240368d 100644 --- a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp +++ b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp @@ -405,6 +405,7 @@ private slots: void multi_byte_code_point_in_expansion(); void trigraph(); void nested_arguments_expansion(); + void preprocessorSymbolsAsMacroArguments(); }; // Remove all #... lines, and 'simplify' string, to allow easily comparing the result @@ -2099,6 +2100,20 @@ void tst_Preprocessor::nested_arguments_expansion() QVERIFY(prep.contains(output)); } +void tst_Preprocessor::preprocessorSymbolsAsMacroArguments() +{ + Environment env; + Preprocessor preprocess(nullptr, &env); + const QByteArray input = + "#define IFGEN(if, endif) if (1 == 0) endif\n" + "int main()\n" + "{\n" + "IFGEN(#if, #endif)\n" + "return 0;\n" + "}\n"; + QVERIFY(preprocess.run(QLatin1String(""), input).startsWith("# 1 \"\"\n")); +} + void tst_Preprocessor::excessive_nesting() { Environment env;