diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index dbdd5e0b6b8993f745a349841c25eb541ebd048d..4479ee8d96a54fba485711d7bbb2fda8980566b1 100644 --- a/src/libs/cplusplus/pp-engine.cpp +++ b/src/libs/cplusplus/pp-engine.cpp @@ -587,7 +587,7 @@ Preprocessor::State Preprocessor::createStateFromSource(const QByteArray &source return state; } -void Preprocessor::processNewline(bool force) +void Preprocessor::processNewline(bool force, int extraLines) { if (_dot != _tokens.constBegin()) { TokenIterator prevTok = _dot - 1; @@ -605,23 +605,25 @@ void Preprocessor::processNewline(bool force) } } - if (! force && env->currentLine == _dot->lineno) + unsigned lineno = _dot->lineno + extraLines; + + if (! force && env->currentLine == lineno) return; - if (force || env->currentLine > _dot->lineno) { + if (force || env->currentLine > lineno) { out("\n# "); - out(QByteArray::number(_dot->lineno)); + out(QByteArray::number(lineno)); out(' '); out('"'); out(env->currentFile.toUtf8()); out('"'); out('\n'); } else { - for (unsigned i = env->currentLine; i < _dot->lineno; ++i) + for (unsigned i = env->currentLine; i < lineno; ++i) out('\n'); } - env->currentLine = _dot->lineno; + env->currentLine = lineno; } void Preprocessor::processSkippingBlocks(bool skippingBlocks, @@ -650,28 +652,33 @@ void Preprocessor::processSkippingBlocks(bool skippingBlocks, bool Preprocessor::markGeneratedTokens(bool markGeneratedTokens, TokenIterator dot) +{ + bool previous = _markGeneratedTokens; + if (previous != markGeneratedTokens) { + if (! dot) + dot = _dot; + const int pos = markGeneratedTokens ? dot->begin() : (dot - 1)->end(); + this->markGeneratedTokens(markGeneratedTokens, pos, dot->lineno - _dot->lineno, dot->f.newline); + } + return previous; +} + +bool Preprocessor::markGeneratedTokens(bool markGeneratedTokens, int position, int extraLines, bool newline) { bool previous = _markGeneratedTokens; _markGeneratedTokens = markGeneratedTokens; if (previous != _markGeneratedTokens) { - if (! dot) - dot = _dot; if (_markGeneratedTokens) out("\n#gen true"); else out("\n#gen false"); - processNewline(/*force = */ true); + processNewline(/*force = */ true, extraLines); const char *begin = _source.constBegin(); - const char *end = begin; - - if (markGeneratedTokens) - end += dot->begin(); - else - end += (dot - 1)->end(); + const char *end = begin + position; const char *it = end - 1; for (; it != begin - 1; --it) { @@ -688,7 +695,7 @@ bool Preprocessor::markGeneratedTokens(bool markGeneratedTokens, out(*it); } - if (! markGeneratedTokens && dot->f.newline) + if (!markGeneratedTokens && newline) processNewline(/*force = */ true); } diff --git a/src/libs/cplusplus/pp-engine.h b/src/libs/cplusplus/pp-engine.h index 3240d3fe9ef2f5f02b59d9eebbd47885f37b0c03..40c3cabaa838f2496dcacb934ed0c81c7ad90f6c 100644 --- a/src/libs/cplusplus/pp-engine.h +++ b/src/libs/cplusplus/pp-engine.h @@ -110,6 +110,7 @@ private: }; bool markGeneratedTokens(bool markGeneratedTokens, TokenIterator dot = 0); + bool markGeneratedTokens(bool markGeneratedTokens, int position, int extraLines=0, bool newline=false); QByteArray expand(const QByteArray &source); void expand(const QByteArray &source, QByteArray *result); @@ -143,7 +144,7 @@ private: void collectActualArguments(QVector *actuals); MacroArgumentReference collectOneActualArgument(); - void processNewline(bool force = false); + void processNewline(bool force = false, int extraLines = 0); void processSkippingBlocks(bool skippingBlocks, TokenIterator dot, TokenIterator lastToken); diff --git a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp index 43c9ca2d56b1900887ad1000b003bee871524a13..35a8c3046b259f312785f3b94ca9201e6f8d6049 100644 --- a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp +++ b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp @@ -45,6 +45,7 @@ private Q_SLOTS: void named_va_args(); void first_empty_macro_arg(); void param_expanding_as_multiple_params(); + void macro_definition_lineno(); void unfinished_function_like_macro_call(); void nasty_macro_expansion(); void tstst(); @@ -114,6 +115,40 @@ void tst_Preprocessor::param_expanding_as_multiple_params() QVERIFY(preprocessed.contains("int f(int a,int b);")); } +void tst_Preprocessor::macro_definition_lineno() +{ + Client *client = 0; // no client. + Environment env; + Preprocessor preprocess(client, &env); + QByteArray preprocessed = preprocess(QLatin1String(""), + QByteArray("#define foo(ARGS) int f(ARGS)\n" + "foo(int a);\n")); + QVERIFY(preprocessed.contains("#gen true\n# 2 ")); + + preprocessed = preprocess(QLatin1String(""), + QByteArray("#define foo(ARGS) int f(ARGS)\n" + "foo(int a)\n" + ";\n")); + QVERIFY(preprocessed.contains("#gen true\n# 2 ")); + + preprocessed = preprocess(QLatin1String(""), + QByteArray("#define foo(ARGS) int f(ARGS)\n" + "foo(int \n" + " a);\n")); + QVERIFY(preprocessed.contains("#gen true\n# 2 ")); + + preprocessed = preprocess(QLatin1String(""), + QByteArray("#define foo int f\n" + "foo;\n")); + QVERIFY(preprocessed.contains("#gen true\n# 2 ")); + + preprocessed = preprocess(QLatin1String(""), + QByteArray("#define foo int f\n" + "foo\n" + ";\n")); + QVERIFY(preprocessed.contains("#gen true\n# 2 ")); +} + void tst_Preprocessor::unfinished_function_like_macro_call() { Client *client = 0; // no client.