Commit 2386d701 authored by Francois Ferrand's avatar Francois Ferrand Committed by Erik Verbruggen

Preprocessor: fix line for generated code.

The macro used to be at the same line as the first token after the
closing parenthesis.

Change-Id: I4c2d7317632baf612900e84572017aeb247d0585
Reviewed-by: default avatarErik Verbruggen <erik.verbruggen@nokia.com>
parent 558b6e08
......@@ -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);
}
......
......@@ -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<MacroArgumentReference> *actuals);
MacroArgumentReference collectOneActualArgument();
void processNewline(bool force = false);
void processNewline(bool force = false, int extraLines = 0);
void processSkippingBlocks(bool skippingBlocks,
TokenIterator dot, TokenIterator lastToken);
......
......@@ -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("<stdin>"),
QByteArray("#define foo(ARGS) int f(ARGS)\n"
"foo(int a);\n"));
QVERIFY(preprocessed.contains("#gen true\n# 2 "));
preprocessed = preprocess(QLatin1String("<stdin>"),
QByteArray("#define foo(ARGS) int f(ARGS)\n"
"foo(int a)\n"
";\n"));
QVERIFY(preprocessed.contains("#gen true\n# 2 "));
preprocessed = preprocess(QLatin1String("<stdin>"),
QByteArray("#define foo(ARGS) int f(ARGS)\n"
"foo(int \n"
" a);\n"));
QVERIFY(preprocessed.contains("#gen true\n# 2 "));
preprocessed = preprocess(QLatin1String("<stdin>"),
QByteArray("#define foo int f\n"
"foo;\n"));
QVERIFY(preprocessed.contains("#gen true\n# 2 "));
preprocessed = preprocess(QLatin1String("<stdin>"),
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.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment