2012-10-02 09:12:39 +02:00
|
|
|
/****************************************************************************
|
2011-02-18 14:48:16 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
|
|
|
|
** Contact: http://www.qt-project.org/legal
|
2011-02-18 14:48:16 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** This file is part of Qt Creator.
|
2011-02-18 14:48:16 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** Commercial License Usage
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
|
|
** a written agreement between you and Digia. For licensing terms and
|
|
|
|
** conditions see http://qt.digia.com/licensing. For further information
|
|
|
|
** use the contact form at http://qt.digia.com/contact-us.
|
2011-02-18 14:48:16 +01:00
|
|
|
**
|
|
|
|
** GNU Lesser General Public License Usage
|
2012-10-02 09:12:39 +02:00
|
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
|
|
** General Public License version 2.1 as published by the Free Software
|
|
|
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
|
|
** packaging of this file. Please review the following information to
|
|
|
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
|
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
|
|
**
|
|
|
|
** In addition, as a special exception, Digia gives you certain additional
|
|
|
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
2011-02-18 14:48:16 +01:00
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
****************************************************************************/
|
2011-02-18 14:48:16 +01:00
|
|
|
|
2009-03-02 11:30:43 +01:00
|
|
|
#include <QtTest>
|
|
|
|
#include <pp.h>
|
2012-05-29 12:37:55 +02:00
|
|
|
#include <QHash>
|
2009-03-02 11:30:43 +01:00
|
|
|
|
2010-09-02 15:32:04 +10:00
|
|
|
//TESTED_COMPONENT=src/libs/cplusplus
|
2009-03-03 16:32:08 +01:00
|
|
|
using namespace CPlusPlus;
|
2009-03-02 11:30:43 +01:00
|
|
|
|
2012-03-26 15:18:01 +02:00
|
|
|
#define DUMP_OUTPUT(x) {QByteArray b(x);qDebug("output: [[%s]]", b.replace("\n", "<<\n").constData());}
|
|
|
|
|
|
|
|
|
|
|
|
QByteArray loadSource(const QString &fileName)
|
|
|
|
{
|
|
|
|
QFile inf(fileName);
|
|
|
|
if (!inf.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
|
|
qDebug("Cannot open \"%s\"", fileName.toUtf8().constData());
|
|
|
|
return QByteArray();
|
|
|
|
}
|
|
|
|
|
|
|
|
QTextStream ins(&inf);
|
|
|
|
QString source = ins.readAll();
|
|
|
|
inf.close();
|
|
|
|
return source.toUtf8();
|
|
|
|
}
|
|
|
|
|
|
|
|
void saveData(const QByteArray &data, const QString &fileName)
|
|
|
|
{
|
|
|
|
QFile inf(fileName);
|
|
|
|
if (!inf.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
|
|
|
qDebug("Cannot open \"%s\"", fileName.toUtf8().constData());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
inf.write(data);
|
|
|
|
inf.close();
|
|
|
|
}
|
|
|
|
|
2012-03-29 17:14:42 +02:00
|
|
|
struct Include
|
|
|
|
{
|
|
|
|
Include(const QString &fileName, Client::IncludeType type, unsigned line)
|
|
|
|
: fileName(fileName), type(type), line(line)
|
|
|
|
{}
|
|
|
|
|
|
|
|
QString fileName;
|
|
|
|
Client::IncludeType type;
|
|
|
|
unsigned line;
|
|
|
|
};
|
2012-04-24 18:29:09 +02:00
|
|
|
|
|
|
|
QDebug &operator<<(QDebug& d, const Include &i)
|
|
|
|
{
|
2012-03-29 17:14:42 +02:00
|
|
|
d << '[' << i.fileName
|
2012-04-24 18:29:09 +02:00
|
|
|
<< ',' << (i.type == Client::IncludeGlobal ? "Global"
|
|
|
|
: (i.type == Client::IncludeLocal ? "Local" : "Unknown"))
|
2012-03-29 17:14:42 +02:00
|
|
|
<< ',' << i.line
|
|
|
|
<< ']';
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
2012-04-24 18:29:09 +02:00
|
|
|
class MockClient : public Client
|
2012-03-26 15:18:01 +02:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
struct Block {
|
2012-04-24 18:29:09 +02:00
|
|
|
Block() : start(0), end(0) {}
|
|
|
|
Block(unsigned start) : start(start), end(0) {}
|
2012-03-26 15:18:01 +02:00
|
|
|
|
|
|
|
unsigned start;
|
|
|
|
unsigned end;
|
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
|
|
|
MockClient(Environment *env, QByteArray *output)
|
|
|
|
: m_env(env)
|
|
|
|
, m_output(output)
|
|
|
|
, m_pp(this, env)
|
|
|
|
, m_includeDepth(0)
|
|
|
|
{}
|
|
|
|
|
|
|
|
virtual ~MockClient() {}
|
|
|
|
|
2012-04-02 14:57:13 +02:00
|
|
|
virtual void macroAdded(const Macro & macro)
|
|
|
|
{
|
|
|
|
m_definedMacros.append(macro.name());
|
|
|
|
m_definedMacrosLine.append(macro.line());
|
|
|
|
}
|
2012-03-26 15:18:01 +02:00
|
|
|
|
C++: Core changes in preprocessing
Summary of most relevant items:
- Preprocessor output format change. No more gen true/false. Instead
a more intuitive and natural expansion (like from a real compiler) is
performed directly corresponding to the macro invocation. Notice that
information about the generated tokens is not lost, because it's now
embedded in the expansion section header (in terms of lines and columns
as explained in the code). In addition the location on where the macro
expansion happens is also documented for future use.
- Fix line control directives and associated token line numbers.
This was not detected in tests cases because some of them were
actually wrong: Within expansions the line information was being
considered as originally computed in the macro definition, while
the desired and expected for Creator's reporting mechanism (just
like regular compilers) is the line from the expanded version
of the tokens.
- Do not allow for eager expansion. This was previously being done
inside define directives. However, it's not allowed and might
lead to incorrect results, since the argument substitution should
only happen upon the macro invocation (and following nested ones).
At least GCC and clang are consistent with that. See test case
tst_Preprocessor:dont_eagerly_expand for a detailed explanation.
- Revive the 'expanded' token flag. This is used to mark every token
that originates from a macro expansion. Notice, however, that
expanded tokens are not necessarily generated tokens (although
every generated token is a expanded token). Expanded tokens that
are not generated are those which are still considered by our
code model features, since they are visible on the editor. The
translation unit is smart enough to calculate line/column position
for such tokens based on the information from the expansion section
header.
- How expansions are tracked has also changed. Now, we simply add
two surrounding marker tokens to each "top-level" expansion
sequence. There is an enumeration that control expansion states.
Also, no "previous" token is kept around.
- Preprocessor client methods suffered a change in signature so
they now receive the line number of the action in question as
a paramater. Previously such line could be retrieved by the client
implementation by accessing the environment line. However, this
is not reliable because we try to avoid synchronization of the
output/environment lines in order to avoid unnecessary output,
while expanding macros or handling preprocessor directives.
- Although macros are not expanded during define directives (as
mentioned above) the preprocessor client is now "notified"
when it sees a macro. This is to allow usage tracking.
- Other small stuff.
This is all in one patch because the fixes are a consequence
of the change in preprocessing control.
Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
|
|
|
virtual void passedMacroDefinitionCheck(unsigned /*offset*/,
|
|
|
|
unsigned /*line*/,
|
|
|
|
const Macro &/*macro*/) {}
|
2012-04-18 17:44:23 +02:00
|
|
|
virtual void failedMacroDefinitionCheck(unsigned /*offset*/, const ByteArrayRef &/*name*/) {}
|
2012-03-26 15:18:01 +02:00
|
|
|
|
C++: Core changes in preprocessing
Summary of most relevant items:
- Preprocessor output format change. No more gen true/false. Instead
a more intuitive and natural expansion (like from a real compiler) is
performed directly corresponding to the macro invocation. Notice that
information about the generated tokens is not lost, because it's now
embedded in the expansion section header (in terms of lines and columns
as explained in the code). In addition the location on where the macro
expansion happens is also documented for future use.
- Fix line control directives and associated token line numbers.
This was not detected in tests cases because some of them were
actually wrong: Within expansions the line information was being
considered as originally computed in the macro definition, while
the desired and expected for Creator's reporting mechanism (just
like regular compilers) is the line from the expanded version
of the tokens.
- Do not allow for eager expansion. This was previously being done
inside define directives. However, it's not allowed and might
lead to incorrect results, since the argument substitution should
only happen upon the macro invocation (and following nested ones).
At least GCC and clang are consistent with that. See test case
tst_Preprocessor:dont_eagerly_expand for a detailed explanation.
- Revive the 'expanded' token flag. This is used to mark every token
that originates from a macro expansion. Notice, however, that
expanded tokens are not necessarily generated tokens (although
every generated token is a expanded token). Expanded tokens that
are not generated are those which are still considered by our
code model features, since they are visible on the editor. The
translation unit is smart enough to calculate line/column position
for such tokens based on the information from the expansion section
header.
- How expansions are tracked has also changed. Now, we simply add
two surrounding marker tokens to each "top-level" expansion
sequence. There is an enumeration that control expansion states.
Also, no "previous" token is kept around.
- Preprocessor client methods suffered a change in signature so
they now receive the line number of the action in question as
a paramater. Previously such line could be retrieved by the client
implementation by accessing the environment line. However, this
is not reliable because we try to avoid synchronization of the
output/environment lines in order to avoid unnecessary output,
while expanding macros or handling preprocessor directives.
- Although macros are not expanded during define directives (as
mentioned above) the preprocessor client is now "notified"
when it sees a macro. This is to allow usage tracking.
- Other small stuff.
This is all in one patch because the fixes are a consequence
of the change in preprocessing control.
Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
|
|
|
virtual void notifyMacroReference(unsigned offset, unsigned line, const Macro ¯o)
|
|
|
|
{
|
|
|
|
m_macroUsesLine[macro.name()].append(line);
|
|
|
|
m_expandedMacrosOffset.append(offset);
|
|
|
|
}
|
|
|
|
|
2012-04-02 13:46:53 +02:00
|
|
|
virtual void startExpandingMacro(unsigned offset,
|
C++: Core changes in preprocessing
Summary of most relevant items:
- Preprocessor output format change. No more gen true/false. Instead
a more intuitive and natural expansion (like from a real compiler) is
performed directly corresponding to the macro invocation. Notice that
information about the generated tokens is not lost, because it's now
embedded in the expansion section header (in terms of lines and columns
as explained in the code). In addition the location on where the macro
expansion happens is also documented for future use.
- Fix line control directives and associated token line numbers.
This was not detected in tests cases because some of them were
actually wrong: Within expansions the line information was being
considered as originally computed in the macro definition, while
the desired and expected for Creator's reporting mechanism (just
like regular compilers) is the line from the expanded version
of the tokens.
- Do not allow for eager expansion. This was previously being done
inside define directives. However, it's not allowed and might
lead to incorrect results, since the argument substitution should
only happen upon the macro invocation (and following nested ones).
At least GCC and clang are consistent with that. See test case
tst_Preprocessor:dont_eagerly_expand for a detailed explanation.
- Revive the 'expanded' token flag. This is used to mark every token
that originates from a macro expansion. Notice, however, that
expanded tokens are not necessarily generated tokens (although
every generated token is a expanded token). Expanded tokens that
are not generated are those which are still considered by our
code model features, since they are visible on the editor. The
translation unit is smart enough to calculate line/column position
for such tokens based on the information from the expansion section
header.
- How expansions are tracked has also changed. Now, we simply add
two surrounding marker tokens to each "top-level" expansion
sequence. There is an enumeration that control expansion states.
Also, no "previous" token is kept around.
- Preprocessor client methods suffered a change in signature so
they now receive the line number of the action in question as
a paramater. Previously such line could be retrieved by the client
implementation by accessing the environment line. However, this
is not reliable because we try to avoid synchronization of the
output/environment lines in order to avoid unnecessary output,
while expanding macros or handling preprocessor directives.
- Although macros are not expanded during define directives (as
mentioned above) the preprocessor client is now "notified"
when it sees a macro. This is to allow usage tracking.
- Other small stuff.
This is all in one patch because the fixes are a consequence
of the change in preprocessing control.
Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
|
|
|
unsigned line,
|
2012-05-29 12:37:55 +02:00
|
|
|
const Macro ¯o,
|
2012-06-12 14:51:48 +02:00
|
|
|
const QVector<MacroArgumentReference> &actuals
|
|
|
|
= QVector<MacroArgumentReference>())
|
2012-04-02 13:46:53 +02:00
|
|
|
{
|
C++: Core changes in preprocessing
Summary of most relevant items:
- Preprocessor output format change. No more gen true/false. Instead
a more intuitive and natural expansion (like from a real compiler) is
performed directly corresponding to the macro invocation. Notice that
information about the generated tokens is not lost, because it's now
embedded in the expansion section header (in terms of lines and columns
as explained in the code). In addition the location on where the macro
expansion happens is also documented for future use.
- Fix line control directives and associated token line numbers.
This was not detected in tests cases because some of them were
actually wrong: Within expansions the line information was being
considered as originally computed in the macro definition, while
the desired and expected for Creator's reporting mechanism (just
like regular compilers) is the line from the expanded version
of the tokens.
- Do not allow for eager expansion. This was previously being done
inside define directives. However, it's not allowed and might
lead to incorrect results, since the argument substitution should
only happen upon the macro invocation (and following nested ones).
At least GCC and clang are consistent with that. See test case
tst_Preprocessor:dont_eagerly_expand for a detailed explanation.
- Revive the 'expanded' token flag. This is used to mark every token
that originates from a macro expansion. Notice, however, that
expanded tokens are not necessarily generated tokens (although
every generated token is a expanded token). Expanded tokens that
are not generated are those which are still considered by our
code model features, since they are visible on the editor. The
translation unit is smart enough to calculate line/column position
for such tokens based on the information from the expansion section
header.
- How expansions are tracked has also changed. Now, we simply add
two surrounding marker tokens to each "top-level" expansion
sequence. There is an enumeration that control expansion states.
Also, no "previous" token is kept around.
- Preprocessor client methods suffered a change in signature so
they now receive the line number of the action in question as
a paramater. Previously such line could be retrieved by the client
implementation by accessing the environment line. However, this
is not reliable because we try to avoid synchronization of the
output/environment lines in order to avoid unnecessary output,
while expanding macros or handling preprocessor directives.
- Although macros are not expanded during define directives (as
mentioned above) the preprocessor client is now "notified"
when it sees a macro. This is to allow usage tracking.
- Other small stuff.
This is all in one patch because the fixes are a consequence
of the change in preprocessing control.
Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
|
|
|
m_expandedMacros.append(macro.name());
|
2012-04-02 13:46:53 +02:00
|
|
|
m_expandedMacrosOffset.append(offset);
|
C++: Core changes in preprocessing
Summary of most relevant items:
- Preprocessor output format change. No more gen true/false. Instead
a more intuitive and natural expansion (like from a real compiler) is
performed directly corresponding to the macro invocation. Notice that
information about the generated tokens is not lost, because it's now
embedded in the expansion section header (in terms of lines and columns
as explained in the code). In addition the location on where the macro
expansion happens is also documented for future use.
- Fix line control directives and associated token line numbers.
This was not detected in tests cases because some of them were
actually wrong: Within expansions the line information was being
considered as originally computed in the macro definition, while
the desired and expected for Creator's reporting mechanism (just
like regular compilers) is the line from the expanded version
of the tokens.
- Do not allow for eager expansion. This was previously being done
inside define directives. However, it's not allowed and might
lead to incorrect results, since the argument substitution should
only happen upon the macro invocation (and following nested ones).
At least GCC and clang are consistent with that. See test case
tst_Preprocessor:dont_eagerly_expand for a detailed explanation.
- Revive the 'expanded' token flag. This is used to mark every token
that originates from a macro expansion. Notice, however, that
expanded tokens are not necessarily generated tokens (although
every generated token is a expanded token). Expanded tokens that
are not generated are those which are still considered by our
code model features, since they are visible on the editor. The
translation unit is smart enough to calculate line/column position
for such tokens based on the information from the expansion section
header.
- How expansions are tracked has also changed. Now, we simply add
two surrounding marker tokens to each "top-level" expansion
sequence. There is an enumeration that control expansion states.
Also, no "previous" token is kept around.
- Preprocessor client methods suffered a change in signature so
they now receive the line number of the action in question as
a paramater. Previously such line could be retrieved by the client
implementation by accessing the environment line. However, this
is not reliable because we try to avoid synchronization of the
output/environment lines in order to avoid unnecessary output,
while expanding macros or handling preprocessor directives.
- Although macros are not expanded during define directives (as
mentioned above) the preprocessor client is now "notified"
when it sees a macro. This is to allow usage tracking.
- Other small stuff.
This is all in one patch because the fixes are a consequence
of the change in preprocessing control.
Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
|
|
|
m_macroUsesLine[macro.name()].append(line);
|
2012-06-12 14:51:48 +02:00
|
|
|
m_macroArgsCount.append(actuals.size());
|
2012-04-02 13:46:53 +02:00
|
|
|
}
|
2012-03-26 15:18:01 +02:00
|
|
|
|
2012-04-24 18:29:09 +02:00
|
|
|
virtual void stopExpandingMacro(unsigned /*offset*/, const Macro &/*macro*/) {}
|
2012-03-26 15:18:01 +02:00
|
|
|
|
|
|
|
virtual void startSkippingBlocks(unsigned offset)
|
|
|
|
{ m_skippedBlocks.append(Block(offset)); }
|
|
|
|
|
|
|
|
virtual void stopSkippingBlocks(unsigned offset)
|
|
|
|
{ m_skippedBlocks.last().end = offset; }
|
|
|
|
|
C++: Core changes in preprocessing
Summary of most relevant items:
- Preprocessor output format change. No more gen true/false. Instead
a more intuitive and natural expansion (like from a real compiler) is
performed directly corresponding to the macro invocation. Notice that
information about the generated tokens is not lost, because it's now
embedded in the expansion section header (in terms of lines and columns
as explained in the code). In addition the location on where the macro
expansion happens is also documented for future use.
- Fix line control directives and associated token line numbers.
This was not detected in tests cases because some of them were
actually wrong: Within expansions the line information was being
considered as originally computed in the macro definition, while
the desired and expected for Creator's reporting mechanism (just
like regular compilers) is the line from the expanded version
of the tokens.
- Do not allow for eager expansion. This was previously being done
inside define directives. However, it's not allowed and might
lead to incorrect results, since the argument substitution should
only happen upon the macro invocation (and following nested ones).
At least GCC and clang are consistent with that. See test case
tst_Preprocessor:dont_eagerly_expand for a detailed explanation.
- Revive the 'expanded' token flag. This is used to mark every token
that originates from a macro expansion. Notice, however, that
expanded tokens are not necessarily generated tokens (although
every generated token is a expanded token). Expanded tokens that
are not generated are those which are still considered by our
code model features, since they are visible on the editor. The
translation unit is smart enough to calculate line/column position
for such tokens based on the information from the expansion section
header.
- How expansions are tracked has also changed. Now, we simply add
two surrounding marker tokens to each "top-level" expansion
sequence. There is an enumeration that control expansion states.
Also, no "previous" token is kept around.
- Preprocessor client methods suffered a change in signature so
they now receive the line number of the action in question as
a paramater. Previously such line could be retrieved by the client
implementation by accessing the environment line. However, this
is not reliable because we try to avoid synchronization of the
output/environment lines in order to avoid unnecessary output,
while expanding macros or handling preprocessor directives.
- Although macros are not expanded during define directives (as
mentioned above) the preprocessor client is now "notified"
when it sees a macro. This is to allow usage tracking.
- Other small stuff.
This is all in one patch because the fixes are a consequence
of the change in preprocessing control.
Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
|
|
|
virtual void sourceNeeded(unsigned line, QString &includedFileName, IncludeType mode)
|
2012-03-26 15:18:01 +02:00
|
|
|
{
|
2012-03-29 17:14:42 +02:00
|
|
|
#if 1
|
|
|
|
m_recordedIncludes.append(Include(includedFileName, mode, line));
|
|
|
|
#else
|
|
|
|
Q_UNUSED(line);
|
|
|
|
|
2012-03-26 15:18:01 +02:00
|
|
|
QString resolvedFileName;
|
|
|
|
if (mode == IncludeLocal)
|
|
|
|
resolvedFileName = resolveLocally(m_env->currentFile, includedFileName);
|
|
|
|
else
|
|
|
|
resolvedFileName = resolveGlobally(includedFileName);
|
|
|
|
|
|
|
|
// qDebug("resolved [[%s]] to [[%s]] from [[%s]] (%s)\n",
|
|
|
|
// includedFileName.toUtf8().constData(),
|
|
|
|
// resolvedFileName.toUtf8().constData(),
|
|
|
|
// currentFileName.toUtf8().constData(),
|
|
|
|
// (mode == IncludeLocal) ? "locally" : "globally");
|
|
|
|
|
|
|
|
if (resolvedFileName.isEmpty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
++m_includeDepth;
|
|
|
|
// qDebug("%5d %s %s", m_includeDepth, QByteArray(m_includeDepth, '+').constData(), resolvedFileName.toUtf8().constData());
|
|
|
|
sourceNeeded(resolvedFileName);
|
|
|
|
--m_includeDepth;
|
2012-03-29 17:14:42 +02:00
|
|
|
#endif
|
2012-03-26 15:18:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QString resolveLocally(const QString ¤tFileName,
|
2012-04-24 18:29:09 +02:00
|
|
|
const QString &includedFileName) const
|
2012-03-26 15:18:01 +02:00
|
|
|
{
|
|
|
|
QDir dir;
|
|
|
|
if (currentFileName.isEmpty())
|
|
|
|
dir = QDir::current();
|
|
|
|
else
|
|
|
|
dir = QFileInfo(currentFileName).dir();
|
|
|
|
const QFileInfo inc(dir, includedFileName);
|
|
|
|
if (inc.exists()) {
|
|
|
|
const QString resolved = inc.filePath();
|
|
|
|
return resolved.toUtf8().constData();
|
|
|
|
} else {
|
|
|
|
// std::cerr<<"Cannot find " << inc.fileName().toUtf8().constData()<<std::endl;
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QString resolveGlobally(const QString ¤tFileName) const
|
|
|
|
{
|
|
|
|
foreach (const QDir &dir, m_includePaths) {
|
|
|
|
QFileInfo f(dir, currentFileName);
|
|
|
|
if (f.exists())
|
|
|
|
return f.filePath();
|
|
|
|
}
|
|
|
|
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
|
|
|
void setIncludePaths(const QStringList &includePaths)
|
|
|
|
{
|
|
|
|
foreach (const QString &path, includePaths) {
|
|
|
|
QDir dir(path);
|
|
|
|
if (dir.exists())
|
|
|
|
m_includePaths.append(dir);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-30 13:01:32 +02:00
|
|
|
void sourceNeeded(const QString &fileName, bool nolines)
|
2012-03-26 15:18:01 +02:00
|
|
|
{
|
|
|
|
QByteArray src = loadSource(fileName);
|
|
|
|
QVERIFY(!src.isEmpty());
|
2012-04-19 10:35:49 +02:00
|
|
|
*m_output = m_pp.run(fileName, src, nolines, true);
|
2012-03-26 15:18:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QList<Block> skippedBlocks() const
|
|
|
|
{ return m_skippedBlocks; }
|
|
|
|
|
2012-03-29 17:14:42 +02:00
|
|
|
QList<Include> recordedIncludes() const
|
|
|
|
{ return m_recordedIncludes; }
|
|
|
|
|
2012-04-02 08:46:56 +02:00
|
|
|
QList<QByteArray> expandedMacros() const
|
|
|
|
{ return m_expandedMacros; }
|
|
|
|
|
2012-04-02 13:46:53 +02:00
|
|
|
QList<unsigned> expandedMacrosOffset() const
|
|
|
|
{ return m_expandedMacrosOffset; }
|
|
|
|
|
2012-04-02 14:57:13 +02:00
|
|
|
QList<QByteArray> definedMacros() const
|
|
|
|
{ return m_definedMacros; }
|
|
|
|
|
|
|
|
QList<unsigned> definedMacrosLine() const
|
|
|
|
{ return m_definedMacrosLine; }
|
|
|
|
|
2012-05-29 15:27:56 +02:00
|
|
|
QHash<QByteArray, QList<unsigned> > macroUsesLine() const
|
2012-05-29 12:37:55 +02:00
|
|
|
{ return m_macroUsesLine; }
|
|
|
|
|
2012-06-12 14:51:48 +02:00
|
|
|
const QList<int> macroArgsCount() const
|
|
|
|
{ return m_macroArgsCount; }
|
|
|
|
|
2012-03-26 15:18:01 +02:00
|
|
|
private:
|
|
|
|
Environment *m_env;
|
|
|
|
QByteArray *m_output;
|
|
|
|
Preprocessor m_pp;
|
|
|
|
QList<QDir> m_includePaths;
|
|
|
|
unsigned m_includeDepth;
|
|
|
|
QList<Block> m_skippedBlocks;
|
2012-03-29 17:14:42 +02:00
|
|
|
QList<Include> m_recordedIncludes;
|
2012-04-02 08:46:56 +02:00
|
|
|
QList<QByteArray> m_expandedMacros;
|
2012-04-02 13:46:53 +02:00
|
|
|
QList<unsigned> m_expandedMacrosOffset;
|
2012-04-02 14:57:13 +02:00
|
|
|
QList<QByteArray> m_definedMacros;
|
|
|
|
QList<unsigned> m_definedMacrosLine;
|
2012-05-29 15:27:56 +02:00
|
|
|
QHash<QByteArray, QList<unsigned> > m_macroUsesLine;
|
2012-06-12 14:51:48 +02:00
|
|
|
QList<int> m_macroArgsCount;
|
2012-03-26 15:18:01 +02:00
|
|
|
};
|
|
|
|
|
2012-04-16 11:39:46 +02:00
|
|
|
QT_BEGIN_NAMESPACE
|
2012-04-02 13:46:53 +02:00
|
|
|
namespace QTest {
|
|
|
|
template<> char *toString(const QList<unsigned> &list)
|
|
|
|
{
|
|
|
|
QByteArray ba = "QList<unsigned>(";
|
|
|
|
foreach (const unsigned& item, list) {
|
|
|
|
ba += QTest::toString(item);
|
|
|
|
ba += ',';
|
|
|
|
}
|
|
|
|
if (!list.isEmpty())
|
|
|
|
ba[ba.size() - 1] = ')';
|
|
|
|
return qstrdup(ba.data());
|
|
|
|
}
|
|
|
|
template<> char *toString(const QList<QByteArray> &list)
|
|
|
|
{
|
|
|
|
QByteArray ba = "QList<QByteArray>(";
|
|
|
|
foreach (const QByteArray& item, list) {
|
|
|
|
ba += QTest::toString(item);
|
|
|
|
ba += ',';
|
|
|
|
}
|
|
|
|
if (!list.isEmpty())
|
|
|
|
ba[ba.size() - 1] = ')';
|
|
|
|
return qstrdup(ba.data());
|
|
|
|
}
|
|
|
|
}
|
2012-04-16 11:39:46 +02:00
|
|
|
QT_END_NAMESPACE
|
2012-04-02 13:46:53 +02:00
|
|
|
|
2012-04-24 18:29:09 +02:00
|
|
|
QDebug &operator<<(QDebug& d, const MockClient::Block &b)
|
|
|
|
{
|
|
|
|
d << '[' << b.start << ',' << b.end << ']';
|
|
|
|
return d;
|
|
|
|
}
|
2012-03-26 15:18:01 +02:00
|
|
|
|
2012-04-24 18:29:09 +02:00
|
|
|
class tst_Preprocessor : public QObject
|
2009-03-02 11:30:43 +01:00
|
|
|
{
|
2012-03-26 15:18:01 +02:00
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
protected:
|
2012-03-30 13:01:32 +02:00
|
|
|
QByteArray preprocess(const QString &fileName, QByteArray * /*errors*/, bool nolines) {
|
2012-03-26 15:18:01 +02:00
|
|
|
//### TODO: hook up errors
|
|
|
|
QByteArray output;
|
|
|
|
Environment env;
|
|
|
|
MockClient client(&env, &output);
|
2012-03-30 13:01:32 +02:00
|
|
|
client.sourceNeeded("data/" + fileName, nolines);
|
2012-03-26 15:18:01 +02:00
|
|
|
return output;
|
|
|
|
}
|
2012-04-02 13:46:53 +02:00
|
|
|
static QString simplified(QByteArray buf);
|
2009-03-02 11:30:43 +01:00
|
|
|
|
C++: Core changes in preprocessing
Summary of most relevant items:
- Preprocessor output format change. No more gen true/false. Instead
a more intuitive and natural expansion (like from a real compiler) is
performed directly corresponding to the macro invocation. Notice that
information about the generated tokens is not lost, because it's now
embedded in the expansion section header (in terms of lines and columns
as explained in the code). In addition the location on where the macro
expansion happens is also documented for future use.
- Fix line control directives and associated token line numbers.
This was not detected in tests cases because some of them were
actually wrong: Within expansions the line information was being
considered as originally computed in the macro definition, while
the desired and expected for Creator's reporting mechanism (just
like regular compilers) is the line from the expanded version
of the tokens.
- Do not allow for eager expansion. This was previously being done
inside define directives. However, it's not allowed and might
lead to incorrect results, since the argument substitution should
only happen upon the macro invocation (and following nested ones).
At least GCC and clang are consistent with that. See test case
tst_Preprocessor:dont_eagerly_expand for a detailed explanation.
- Revive the 'expanded' token flag. This is used to mark every token
that originates from a macro expansion. Notice, however, that
expanded tokens are not necessarily generated tokens (although
every generated token is a expanded token). Expanded tokens that
are not generated are those which are still considered by our
code model features, since they are visible on the editor. The
translation unit is smart enough to calculate line/column position
for such tokens based on the information from the expansion section
header.
- How expansions are tracked has also changed. Now, we simply add
two surrounding marker tokens to each "top-level" expansion
sequence. There is an enumeration that control expansion states.
Also, no "previous" token is kept around.
- Preprocessor client methods suffered a change in signature so
they now receive the line number of the action in question as
a paramater. Previously such line could be retrieved by the client
implementation by accessing the environment line. However, this
is not reliable because we try to avoid synchronization of the
output/environment lines in order to avoid unnecessary output,
while expanding macros or handling preprocessor directives.
- Although macros are not expanded during define directives (as
mentioned above) the preprocessor client is now "notified"
when it sees a macro. This is to allow usage tracking.
- Other small stuff.
This is all in one patch because the fixes are a consequence
of the change in preprocessing control.
Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
|
|
|
private:
|
2012-08-07 10:47:38 +02:00
|
|
|
void compare_input_output(bool keepComments = false);
|
2012-06-13 09:50:39 +02:00
|
|
|
|
2012-03-26 15:18:01 +02:00
|
|
|
private slots:
|
2012-03-16 14:06:09 +01:00
|
|
|
void va_args();
|
|
|
|
void named_va_args();
|
C++: Core changes in preprocessing
Summary of most relevant items:
- Preprocessor output format change. No more gen true/false. Instead
a more intuitive and natural expansion (like from a real compiler) is
performed directly corresponding to the macro invocation. Notice that
information about the generated tokens is not lost, because it's now
embedded in the expansion section header (in terms of lines and columns
as explained in the code). In addition the location on where the macro
expansion happens is also documented for future use.
- Fix line control directives and associated token line numbers.
This was not detected in tests cases because some of them were
actually wrong: Within expansions the line information was being
considered as originally computed in the macro definition, while
the desired and expected for Creator's reporting mechanism (just
like regular compilers) is the line from the expanded version
of the tokens.
- Do not allow for eager expansion. This was previously being done
inside define directives. However, it's not allowed and might
lead to incorrect results, since the argument substitution should
only happen upon the macro invocation (and following nested ones).
At least GCC and clang are consistent with that. See test case
tst_Preprocessor:dont_eagerly_expand for a detailed explanation.
- Revive the 'expanded' token flag. This is used to mark every token
that originates from a macro expansion. Notice, however, that
expanded tokens are not necessarily generated tokens (although
every generated token is a expanded token). Expanded tokens that
are not generated are those which are still considered by our
code model features, since they are visible on the editor. The
translation unit is smart enough to calculate line/column position
for such tokens based on the information from the expansion section
header.
- How expansions are tracked has also changed. Now, we simply add
two surrounding marker tokens to each "top-level" expansion
sequence. There is an enumeration that control expansion states.
Also, no "previous" token is kept around.
- Preprocessor client methods suffered a change in signature so
they now receive the line number of the action in question as
a paramater. Previously such line could be retrieved by the client
implementation by accessing the environment line. However, this
is not reliable because we try to avoid synchronization of the
output/environment lines in order to avoid unnecessary output,
while expanding macros or handling preprocessor directives.
- Although macros are not expanded during define directives (as
mentioned above) the preprocessor client is now "notified"
when it sees a macro. This is to allow usage tracking.
- Other small stuff.
This is all in one patch because the fixes are a consequence
of the change in preprocessing control.
Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
|
|
|
void defined();
|
|
|
|
void defined_data();
|
2012-06-12 14:51:48 +02:00
|
|
|
void empty_macro_args();
|
|
|
|
void macro_args_count();
|
2012-03-26 15:18:01 +02:00
|
|
|
void invalid_param_count();
|
2012-04-02 08:46:56 +02:00
|
|
|
void objmacro_expanding_as_fnmacro_notification();
|
2012-04-02 13:46:53 +02:00
|
|
|
void macro_uses();
|
2012-05-29 12:37:55 +02:00
|
|
|
void macro_uses_lines();
|
2012-04-02 08:46:56 +02:00
|
|
|
void macro_arguments_notificatin();
|
2009-03-03 16:32:08 +01:00
|
|
|
void unfinished_function_like_macro_call();
|
2010-02-10 11:04:31 +01:00
|
|
|
void nasty_macro_expansion();
|
C++: Core changes in preprocessing
Summary of most relevant items:
- Preprocessor output format change. No more gen true/false. Instead
a more intuitive and natural expansion (like from a real compiler) is
performed directly corresponding to the macro invocation. Notice that
information about the generated tokens is not lost, because it's now
embedded in the expansion section header (in terms of lines and columns
as explained in the code). In addition the location on where the macro
expansion happens is also documented for future use.
- Fix line control directives and associated token line numbers.
This was not detected in tests cases because some of them were
actually wrong: Within expansions the line information was being
considered as originally computed in the macro definition, while
the desired and expected for Creator's reporting mechanism (just
like regular compilers) is the line from the expanded version
of the tokens.
- Do not allow for eager expansion. This was previously being done
inside define directives. However, it's not allowed and might
lead to incorrect results, since the argument substitution should
only happen upon the macro invocation (and following nested ones).
At least GCC and clang are consistent with that. See test case
tst_Preprocessor:dont_eagerly_expand for a detailed explanation.
- Revive the 'expanded' token flag. This is used to mark every token
that originates from a macro expansion. Notice, however, that
expanded tokens are not necessarily generated tokens (although
every generated token is a expanded token). Expanded tokens that
are not generated are those which are still considered by our
code model features, since they are visible on the editor. The
translation unit is smart enough to calculate line/column position
for such tokens based on the information from the expansion section
header.
- How expansions are tracked has also changed. Now, we simply add
two surrounding marker tokens to each "top-level" expansion
sequence. There is an enumeration that control expansion states.
Also, no "previous" token is kept around.
- Preprocessor client methods suffered a change in signature so
they now receive the line number of the action in question as
a paramater. Previously such line could be retrieved by the client
implementation by accessing the environment line. However, this
is not reliable because we try to avoid synchronization of the
output/environment lines in order to avoid unnecessary output,
while expanding macros or handling preprocessor directives.
- Although macros are not expanded during define directives (as
mentioned above) the preprocessor client is now "notified"
when it sees a macro. This is to allow usage tracking.
- Other small stuff.
This is all in one patch because the fixes are a consequence
of the change in preprocessing control.
Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
|
|
|
void glib_attribute();
|
|
|
|
void builtin__FILE__();
|
2012-03-26 15:18:01 +02:00
|
|
|
void blockSkipping();
|
2012-03-29 17:14:42 +02:00
|
|
|
void includes_1();
|
C++: Core changes in preprocessing
Summary of most relevant items:
- Preprocessor output format change. No more gen true/false. Instead
a more intuitive and natural expansion (like from a real compiler) is
performed directly corresponding to the macro invocation. Notice that
information about the generated tokens is not lost, because it's now
embedded in the expansion section header (in terms of lines and columns
as explained in the code). In addition the location on where the macro
expansion happens is also documented for future use.
- Fix line control directives and associated token line numbers.
This was not detected in tests cases because some of them were
actually wrong: Within expansions the line information was being
considered as originally computed in the macro definition, while
the desired and expected for Creator's reporting mechanism (just
like regular compilers) is the line from the expanded version
of the tokens.
- Do not allow for eager expansion. This was previously being done
inside define directives. However, it's not allowed and might
lead to incorrect results, since the argument substitution should
only happen upon the macro invocation (and following nested ones).
At least GCC and clang are consistent with that. See test case
tst_Preprocessor:dont_eagerly_expand for a detailed explanation.
- Revive the 'expanded' token flag. This is used to mark every token
that originates from a macro expansion. Notice, however, that
expanded tokens are not necessarily generated tokens (although
every generated token is a expanded token). Expanded tokens that
are not generated are those which are still considered by our
code model features, since they are visible on the editor. The
translation unit is smart enough to calculate line/column position
for such tokens based on the information from the expansion section
header.
- How expansions are tracked has also changed. Now, we simply add
two surrounding marker tokens to each "top-level" expansion
sequence. There is an enumeration that control expansion states.
Also, no "previous" token is kept around.
- Preprocessor client methods suffered a change in signature so
they now receive the line number of the action in question as
a paramater. Previously such line could be retrieved by the client
implementation by accessing the environment line. However, this
is not reliable because we try to avoid synchronization of the
output/environment lines in order to avoid unnecessary output,
while expanding macros or handling preprocessor directives.
- Although macros are not expanded during define directives (as
mentioned above) the preprocessor client is now "notified"
when it sees a macro. This is to allow usage tracking.
- Other small stuff.
This is all in one patch because the fixes are a consequence
of the change in preprocessing control.
Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
|
|
|
void dont_eagerly_expand();
|
|
|
|
void dont_eagerly_expand_data();
|
2012-03-26 15:18:01 +02:00
|
|
|
void comparisons_data();
|
|
|
|
void comparisons();
|
C++: Core changes in preprocessing
Summary of most relevant items:
- Preprocessor output format change. No more gen true/false. Instead
a more intuitive and natural expansion (like from a real compiler) is
performed directly corresponding to the macro invocation. Notice that
information about the generated tokens is not lost, because it's now
embedded in the expansion section header (in terms of lines and columns
as explained in the code). In addition the location on where the macro
expansion happens is also documented for future use.
- Fix line control directives and associated token line numbers.
This was not detected in tests cases because some of them were
actually wrong: Within expansions the line information was being
considered as originally computed in the macro definition, while
the desired and expected for Creator's reporting mechanism (just
like regular compilers) is the line from the expanded version
of the tokens.
- Do not allow for eager expansion. This was previously being done
inside define directives. However, it's not allowed and might
lead to incorrect results, since the argument substitution should
only happen upon the macro invocation (and following nested ones).
At least GCC and clang are consistent with that. See test case
tst_Preprocessor:dont_eagerly_expand for a detailed explanation.
- Revive the 'expanded' token flag. This is used to mark every token
that originates from a macro expansion. Notice, however, that
expanded tokens are not necessarily generated tokens (although
every generated token is a expanded token). Expanded tokens that
are not generated are those which are still considered by our
code model features, since they are visible on the editor. The
translation unit is smart enough to calculate line/column position
for such tokens based on the information from the expansion section
header.
- How expansions are tracked has also changed. Now, we simply add
two surrounding marker tokens to each "top-level" expansion
sequence. There is an enumeration that control expansion states.
Also, no "previous" token is kept around.
- Preprocessor client methods suffered a change in signature so
they now receive the line number of the action in question as
a paramater. Previously such line could be retrieved by the client
implementation by accessing the environment line. However, this
is not reliable because we try to avoid synchronization of the
output/environment lines in order to avoid unnecessary output,
while expanding macros or handling preprocessor directives.
- Although macros are not expanded during define directives (as
mentioned above) the preprocessor client is now "notified"
when it sees a macro. This is to allow usage tracking.
- Other small stuff.
This is all in one patch because the fixes are a consequence
of the change in preprocessing control.
Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
|
|
|
void comments_within();
|
|
|
|
void comments_within_data();
|
2012-08-07 10:47:38 +02:00
|
|
|
void comments_within2();
|
|
|
|
void comments_within2_data();
|
C++: Core changes in preprocessing
Summary of most relevant items:
- Preprocessor output format change. No more gen true/false. Instead
a more intuitive and natural expansion (like from a real compiler) is
performed directly corresponding to the macro invocation. Notice that
information about the generated tokens is not lost, because it's now
embedded in the expansion section header (in terms of lines and columns
as explained in the code). In addition the location on where the macro
expansion happens is also documented for future use.
- Fix line control directives and associated token line numbers.
This was not detected in tests cases because some of them were
actually wrong: Within expansions the line information was being
considered as originally computed in the macro definition, while
the desired and expected for Creator's reporting mechanism (just
like regular compilers) is the line from the expanded version
of the tokens.
- Do not allow for eager expansion. This was previously being done
inside define directives. However, it's not allowed and might
lead to incorrect results, since the argument substitution should
only happen upon the macro invocation (and following nested ones).
At least GCC and clang are consistent with that. See test case
tst_Preprocessor:dont_eagerly_expand for a detailed explanation.
- Revive the 'expanded' token flag. This is used to mark every token
that originates from a macro expansion. Notice, however, that
expanded tokens are not necessarily generated tokens (although
every generated token is a expanded token). Expanded tokens that
are not generated are those which are still considered by our
code model features, since they are visible on the editor. The
translation unit is smart enough to calculate line/column position
for such tokens based on the information from the expansion section
header.
- How expansions are tracked has also changed. Now, we simply add
two surrounding marker tokens to each "top-level" expansion
sequence. There is an enumeration that control expansion states.
Also, no "previous" token is kept around.
- Preprocessor client methods suffered a change in signature so
they now receive the line number of the action in question as
a paramater. Previously such line could be retrieved by the client
implementation by accessing the environment line. However, this
is not reliable because we try to avoid synchronization of the
output/environment lines in order to avoid unnecessary output,
while expanding macros or handling preprocessor directives.
- Although macros are not expanded during define directives (as
mentioned above) the preprocessor client is now "notified"
when it sees a macro. This is to allow usage tracking.
- Other small stuff.
This is all in one patch because the fixes are a consequence
of the change in preprocessing control.
Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
|
|
|
void multitokens_argument();
|
|
|
|
void multitokens_argument_data();
|
2012-08-20 23:11:34 +02:00
|
|
|
void multiline_strings();
|
|
|
|
void multiline_strings_data();
|
2012-08-29 13:21:22 +02:00
|
|
|
void skip_unknown_directives();
|
|
|
|
void skip_unknown_directives_data();
|
2009-03-02 11:30:43 +01:00
|
|
|
};
|
|
|
|
|
2012-04-02 13:46:53 +02:00
|
|
|
// Remove all #... lines, and 'simplify' string, to allow easily comparing the result
|
|
|
|
// Also, remove all unneeded spaces: keep only to ensure identifiers are separated.
|
|
|
|
// NOTE: may not correctly handle underscore in identifiers
|
|
|
|
QString tst_Preprocessor::simplified(QByteArray buf)
|
|
|
|
{
|
|
|
|
QString out;
|
|
|
|
QList<QByteArray> lines = buf.split('\n');
|
2012-04-24 18:29:09 +02:00
|
|
|
foreach (const QByteArray &line, lines) {
|
2012-04-02 13:46:53 +02:00
|
|
|
if (!line.startsWith('#')) {
|
|
|
|
out.append(' ');
|
|
|
|
out.append(line);
|
|
|
|
}
|
2012-04-24 18:29:09 +02:00
|
|
|
}
|
2012-04-02 13:46:53 +02:00
|
|
|
|
|
|
|
out = out.simplified();
|
2012-04-24 18:29:09 +02:00
|
|
|
for (int i = 1; i < out.length() - 1; ) {
|
|
|
|
if (out.at(i).isSpace()
|
|
|
|
&& !(out.at(i-1).isLetterOrNumber()
|
|
|
|
&& out.at(i+1).isLetterOrNumber()))
|
2012-04-02 13:46:53 +02:00
|
|
|
out.remove(i,1);
|
|
|
|
else
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2012-03-16 14:06:09 +01:00
|
|
|
void tst_Preprocessor::va_args()
|
|
|
|
{
|
|
|
|
Client *client = 0; // no client.
|
|
|
|
Environment env;
|
|
|
|
|
|
|
|
Preprocessor preprocess(client, &env);
|
2012-04-19 10:35:49 +02:00
|
|
|
QByteArray preprocessed = preprocess.run(QLatin1String("<stdin>"),
|
|
|
|
"#define foo(...) int f(__VA_ARGS__);\n"
|
|
|
|
"\nfoo( )\n"
|
|
|
|
"\nfoo(int a)\n"
|
|
|
|
"\nfoo(int a,int b)\n",
|
|
|
|
true, false);
|
2012-03-16 14:06:09 +01:00
|
|
|
|
2012-03-26 15:18:01 +02:00
|
|
|
preprocessed = preprocessed.simplified();
|
|
|
|
// DUMP_OUTPUT(preprocessed);
|
2012-04-02 13:46:53 +02:00
|
|
|
QCOMPARE(simplified(preprocessed), QString("int f();int f(int a);int f(int a,int b);"));
|
2012-03-16 14:06:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Preprocessor::named_va_args()
|
|
|
|
{
|
|
|
|
Client *client = 0; // no client.
|
|
|
|
Environment env;
|
|
|
|
|
|
|
|
Preprocessor preprocess(client, &env);
|
2012-04-19 10:35:49 +02:00
|
|
|
QByteArray preprocessed = preprocess.run(QLatin1String("<stdin>"),
|
|
|
|
"\n#define foo(ARGS...) int f(ARGS);"
|
|
|
|
"\nfoo( )\n"
|
|
|
|
"\nfoo(int a)\n"
|
|
|
|
"\nfoo(int a,int b)\n",
|
|
|
|
true, false);
|
2012-03-16 14:06:09 +01:00
|
|
|
|
2012-03-26 15:18:01 +02:00
|
|
|
preprocessed = preprocessed.simplified();
|
2012-04-02 13:46:53 +02:00
|
|
|
QCOMPARE(simplified(preprocessed), QString("int f();int f(int a);int f(int a,int b);"));
|
2012-03-16 14:06:09 +01:00
|
|
|
}
|
|
|
|
|
2012-06-12 14:51:48 +02:00
|
|
|
void tst_Preprocessor::empty_macro_args()
|
2012-03-16 14:10:46 +01:00
|
|
|
{
|
|
|
|
Client *client = 0; // no client.
|
|
|
|
Environment env;
|
|
|
|
|
|
|
|
Preprocessor preprocess(client, &env);
|
2012-04-19 10:35:49 +02:00
|
|
|
QByteArray preprocessed = preprocess.run(QLatin1String("<stdin>"),
|
|
|
|
"\n#define foo(a,b) a int b;"
|
|
|
|
"\nfoo(const,cVal)\n"
|
|
|
|
"\nfoo(,Val)\n"
|
2012-06-12 14:51:48 +02:00
|
|
|
"\nfoo( ,Val2)\n"
|
|
|
|
"\nfoo(,)\n"
|
|
|
|
"\nfoo(, )\n",
|
2012-04-19 10:35:49 +02:00
|
|
|
true, false);
|
2012-03-16 14:10:46 +01:00
|
|
|
|
2012-03-26 15:18:01 +02:00
|
|
|
preprocessed = preprocessed.simplified();
|
|
|
|
// DUMP_OUTPUT(preprocessed);
|
2012-06-12 14:51:48 +02:00
|
|
|
QCOMPARE(simplified(preprocessed),
|
|
|
|
QString("const int cVal;int Val;int Val2;int;int;"));
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Preprocessor::macro_args_count()
|
|
|
|
{
|
|
|
|
Environment env;
|
|
|
|
QByteArray output;
|
|
|
|
MockClient client(&env, &output);
|
|
|
|
Preprocessor preprocess(&client, &env);
|
|
|
|
preprocess.run(QLatin1String("<stdin>"),
|
|
|
|
"#define foo(a,b) a int b;\n"
|
|
|
|
"foo(const,cVal)\n"
|
|
|
|
"foo(, i)\n"
|
|
|
|
"foo(,Val)\n"
|
|
|
|
"foo( ,Val2)\n"
|
|
|
|
"foo(,)\n"
|
|
|
|
"foo(, )\n"
|
|
|
|
"#define bar(a)\n"
|
|
|
|
"bar()\n"
|
|
|
|
"bar(i)\n",
|
|
|
|
true, false);
|
|
|
|
|
|
|
|
QCOMPARE(client.macroArgsCount(),
|
|
|
|
QList<int>() << 2 // foo(const,cVal)
|
|
|
|
<< 2 // foo(, i)
|
|
|
|
<< 2 // foo(,Val)
|
|
|
|
<< 2 // foo( , Val2)
|
|
|
|
<< 2 // foo(,)
|
|
|
|
<< 2 // foo(, )
|
|
|
|
<< 1 // bar()
|
|
|
|
<< 1 // bar(i)
|
|
|
|
);
|
|
|
|
|
2012-03-16 14:10:46 +01:00
|
|
|
}
|
|
|
|
|
2012-03-26 15:18:01 +02:00
|
|
|
void tst_Preprocessor::invalid_param_count()
|
2012-03-16 14:22:17 +01:00
|
|
|
{
|
2012-04-02 13:46:53 +02:00
|
|
|
Environment env;
|
2012-06-12 15:59:07 +02:00
|
|
|
QByteArray output;
|
|
|
|
MockClient client(&env, &output);
|
|
|
|
Preprocessor preprocess(&client, &env);
|
|
|
|
// The following are illegal, but shouldn't crash the preprocessor.
|
|
|
|
preprocess.run(QLatin1String("<stdin>"),
|
|
|
|
"\n#define foo(a,b) int f(a,b);"
|
|
|
|
"\n#define ARGS(t) t a,t b"
|
|
|
|
"\nfoo(ARGS(int))"
|
|
|
|
"\nfoo()"
|
|
|
|
"\nfoo(int a, int b, int c)",
|
|
|
|
true, false);
|
2012-04-02 13:46:53 +02:00
|
|
|
|
2012-06-12 15:59:07 +02:00
|
|
|
// Output is not that relevant but check that nothing triggered expansion.
|
|
|
|
QCOMPARE(client.macroArgsCount(), QList<int>());
|
2012-04-02 13:46:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Preprocessor::macro_uses()
|
|
|
|
{
|
|
|
|
QByteArray buffer = QByteArray("\n#define FOO 8"
|
|
|
|
"\n#define BAR 9"
|
|
|
|
"\nvoid test(){"
|
|
|
|
"\n\tint x=FOO;"
|
|
|
|
"\n\tint y=BAR;"
|
|
|
|
"\n}");
|
|
|
|
|
|
|
|
QByteArray output;
|
|
|
|
Environment env;
|
|
|
|
MockClient client(&env, &output);
|
|
|
|
|
|
|
|
Preprocessor preprocess(&client, &env);
|
2012-04-19 10:35:49 +02:00
|
|
|
QByteArray preprocessed = preprocess.run(QLatin1String("<stdin>"), buffer);
|
2012-04-02 13:46:53 +02:00
|
|
|
QCOMPARE(simplified(preprocessed), QString("void test(){int x=8;int y=9;}"));
|
|
|
|
QCOMPARE(client.expandedMacros(), QList<QByteArray>() << QByteArray("FOO") << QByteArray("BAR"));
|
|
|
|
QCOMPARE(client.expandedMacrosOffset(), QList<unsigned>() << buffer.indexOf("FOO;") << buffer.indexOf("BAR;"));
|
2012-04-02 14:57:13 +02:00
|
|
|
QCOMPARE(client.definedMacros(), QList<QByteArray>() << QByteArray("FOO") << QByteArray("BAR"));
|
|
|
|
QCOMPARE(client.definedMacrosLine(), QList<unsigned>() << 2 << 3);
|
2012-04-02 13:46:53 +02:00
|
|
|
}
|
|
|
|
|
2012-05-29 12:37:55 +02:00
|
|
|
void tst_Preprocessor::macro_uses_lines()
|
|
|
|
{
|
|
|
|
QByteArray buffer("#define FOO\n"
|
|
|
|
"FOO\n"
|
|
|
|
"\n"
|
|
|
|
"#define HEADER <test>\n"
|
|
|
|
"#include HEADER\n"
|
|
|
|
"\n"
|
|
|
|
"#define DECLARE(C, V) struct C {}; C V;\n"
|
|
|
|
"#define ABC X\n"
|
|
|
|
"DECLARE(Test, test)\n"
|
|
|
|
"\n"
|
|
|
|
"int abc;\n"
|
|
|
|
"#define NOTHING(C)\n"
|
|
|
|
"NOTHING(abc)\n"
|
|
|
|
"\n"
|
|
|
|
"#define ENABLE(FEATURE) (defined ENABLE_##FEATURE && ENABLE_##FEATURE)\n"
|
|
|
|
"#define ENABLE_COOL 1\n"
|
|
|
|
"void fill();\n"
|
|
|
|
"#if ENABLE(COOL)\n"
|
|
|
|
"class Cool {};\n"
|
|
|
|
"#endif\n"
|
2012-05-29 15:27:56 +02:00
|
|
|
"int cool = ENABLE_COOL;\n"
|
|
|
|
"#define OTHER_ENABLE(FEATURE) ENABLE(FEATURE)\n"
|
|
|
|
"#define MORE(LESS) FOO ENABLE(LESS)\n");
|
2012-05-29 12:37:55 +02:00
|
|
|
|
|
|
|
QByteArray output;
|
|
|
|
Environment env;
|
|
|
|
MockClient client(&env, &output);
|
|
|
|
Preprocessor preprocess(&client, &env);
|
|
|
|
preprocess.run(QLatin1String("<stdin>"), buffer);
|
|
|
|
|
2012-05-29 15:27:56 +02:00
|
|
|
QCOMPARE(client.macroUsesLine().value("FOO"), QList<unsigned>() << 2U << 23U);
|
|
|
|
QCOMPARE(client.macroUsesLine().value("HEADER"), QList<unsigned>() << 5U);
|
|
|
|
QCOMPARE(client.macroUsesLine().value("DECLARE"), QList<unsigned>() << 9U);
|
|
|
|
QCOMPARE(client.macroUsesLine().value("NOTHING"), QList<unsigned>() << 13U);
|
|
|
|
QCOMPARE(client.macroUsesLine().value("ENABLE"), QList<unsigned>() << 18U << 22U << 23U);
|
|
|
|
QCOMPARE(client.macroUsesLine().value("ENABLE_COOL"), QList<unsigned>() << 21U);
|
2012-05-29 12:37:55 +02:00
|
|
|
QCOMPARE(client.expandedMacrosOffset(), QList<unsigned>()
|
2012-05-29 15:27:56 +02:00
|
|
|
<< buffer.lastIndexOf("FOO\n")
|
2012-05-29 12:37:55 +02:00
|
|
|
<< buffer.lastIndexOf("HEADER")
|
|
|
|
<< buffer.lastIndexOf("DECLARE")
|
|
|
|
<< buffer.lastIndexOf("NOTHING")
|
|
|
|
<< buffer.lastIndexOf("ENABLE(COOL)")
|
2012-05-29 15:27:56 +02:00
|
|
|
<< buffer.lastIndexOf("ENABLE_COOL")
|
|
|
|
<< buffer.lastIndexOf("ENABLE(FEATURE)")
|
|
|
|
<< buffer.lastIndexOf("FOO ")
|
|
|
|
<< buffer.lastIndexOf("ENABLE(LESS)"));
|
2012-05-29 12:37:55 +02:00
|
|
|
}
|
|
|
|
|
C++: Core changes in preprocessing
Summary of most relevant items:
- Preprocessor output format change. No more gen true/false. Instead
a more intuitive and natural expansion (like from a real compiler) is
performed directly corresponding to the macro invocation. Notice that
information about the generated tokens is not lost, because it's now
embedded in the expansion section header (in terms of lines and columns
as explained in the code). In addition the location on where the macro
expansion happens is also documented for future use.
- Fix line control directives and associated token line numbers.
This was not detected in tests cases because some of them were
actually wrong: Within expansions the line information was being
considered as originally computed in the macro definition, while
the desired and expected for Creator's reporting mechanism (just
like regular compilers) is the line from the expanded version
of the tokens.
- Do not allow for eager expansion. This was previously being done
inside define directives. However, it's not allowed and might
lead to incorrect results, since the argument substitution should
only happen upon the macro invocation (and following nested ones).
At least GCC and clang are consistent with that. See test case
tst_Preprocessor:dont_eagerly_expand for a detailed explanation.
- Revive the 'expanded' token flag. This is used to mark every token
that originates from a macro expansion. Notice, however, that
expanded tokens are not necessarily generated tokens (although
every generated token is a expanded token). Expanded tokens that
are not generated are those which are still considered by our
code model features, since they are visible on the editor. The
translation unit is smart enough to calculate line/column position
for such tokens based on the information from the expansion section
header.
- How expansions are tracked has also changed. Now, we simply add
two surrounding marker tokens to each "top-level" expansion
sequence. There is an enumeration that control expansion states.
Also, no "previous" token is kept around.
- Preprocessor client methods suffered a change in signature so
they now receive the line number of the action in question as
a paramater. Previously such line could be retrieved by the client
implementation by accessing the environment line. However, this
is not reliable because we try to avoid synchronization of the
output/environment lines in order to avoid unnecessary output,
while expanding macros or handling preprocessor directives.
- Although macros are not expanded during define directives (as
mentioned above) the preprocessor client is now "notified"
when it sees a macro. This is to allow usage tracking.
- Other small stuff.
This is all in one patch because the fixes are a consequence
of the change in preprocessing control.
Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
|
|
|
void tst_Preprocessor::multitokens_argument_data()
|
2012-03-16 15:16:06 +01:00
|
|
|
{
|
C++: Core changes in preprocessing
Summary of most relevant items:
- Preprocessor output format change. No more gen true/false. Instead
a more intuitive and natural expansion (like from a real compiler) is
performed directly corresponding to the macro invocation. Notice that
information about the generated tokens is not lost, because it's now
embedded in the expansion section header (in terms of lines and columns
as explained in the code). In addition the location on where the macro
expansion happens is also documented for future use.
- Fix line control directives and associated token line numbers.
This was not detected in tests cases because some of them were
actually wrong: Within expansions the line information was being
considered as originally computed in the macro definition, while
the desired and expected for Creator's reporting mechanism (just
like regular compilers) is the line from the expanded version
of the tokens.
- Do not allow for eager expansion. This was previously being done
inside define directives. However, it's not allowed and might
lead to incorrect results, since the argument substitution should
only happen upon the macro invocation (and following nested ones).
At least GCC and clang are consistent with that. See test case
tst_Preprocessor:dont_eagerly_expand for a detailed explanation.
- Revive the 'expanded' token flag. This is used to mark every token
that originates from a macro expansion. Notice, however, that
expanded tokens are not necessarily generated tokens (although
every generated token is a expanded token). Expanded tokens that
are not generated are those which are still considered by our
code model features, since they are visible on the editor. The
translation unit is smart enough to calculate line/column position
for such tokens based on the information from the expansion section
header.
- How expansions are tracked has also changed. Now, we simply add
two surrounding marker tokens to each "top-level" expansion
sequence. There is an enumeration that control expansion states.
Also, no "previous" token is kept around.
- Preprocessor client methods suffered a change in signature so
they now receive the line number of the action in question as
a paramater. Previously such line could be retrieved by the client
implementation by accessing the environment line. However, this
is not reliable because we try to avoid synchronization of the
output/environment lines in order to avoid unnecessary output,
while expanding macros or handling preprocessor directives.
- Although macros are not expanded during define directives (as
mentioned above) the preprocessor client is now "notified"
when it sees a macro. This is to allow usage tracking.
- Other small stuff.
This is all in one patch because the fixes are a consequence
of the change in preprocessing control.
Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
|
|
|
QTest::addColumn<QByteArray>("input");
|
|
|
|
QTest::addColumn<QByteArray>("output");
|
|
|
|
|
|
|
|
QByteArray original;
|
|
|
|
QByteArray expected;
|
|
|
|
|
|
|
|
original =
|
|
|
|
"#define foo(ARGS) int f(ARGS)\n"
|
|
|
|
"foo(int a);\n";
|
|
|
|
expected =
|
|
|
|
"# 1 \"<stdin>\"\n"
|
|
|
|
"\n"
|
|
|
|
"# expansion begin 30,3 ~3 2:4 2:8 ~1\n"
|
|
|
|
"int f(int a)\n"
|
|
|
|
"# expansion end\n"
|
|
|
|
"# 2 \"<stdin>\"\n"
|
|
|
|
" ;\n";
|
|
|
|
QTest::newRow("case 1") << original << expected;
|
|
|
|
|
|
|
|
original =
|
|
|
|
"#define foo(ARGS) int f(ARGS)\n"
|
|
|
|
"foo(int \n"
|
|
|
|
" a);\n";
|
|
|
|
expected =
|
|
|
|
"# 1 \"<stdin>\"\n"
|
|
|
|
"\n"
|
|
|
|
"# expansion begin 30,3 ~3 2:4 3:4 ~1\n"
|
|
|
|
"int f(int a)\n"
|
|
|
|
"# expansion end\n"
|
|
|
|
"# 3 \"<stdin>\"\n"
|
|
|
|
" ;\n";
|
|
|
|
QTest::newRow("case 2") << original << expected;
|
|
|
|
|
|
|
|
original =
|
|
|
|
"#define foo(ARGS) int f(ARGS)\n"
|
|
|
|
"foo(int a = 0);\n";
|
|
|
|
expected =
|
|
|
|
"# 1 \"<stdin>\"\n"
|
|
|
|
"\n"
|
|
|
|
"# expansion begin 30,3 ~3 2:4 2:8 2:10 2:12 ~1\n"
|
|
|
|
"int f(int a = 0)\n"
|
|
|
|
"# expansion end\n"
|
|
|
|
"# 2 \"<stdin>\"\n"
|
|
|
|
" ;\n";
|
|
|
|
QTest::newRow("case 3") << original << expected;
|
|
|
|
|
|
|
|
original =
|
|
|
|
"#define foo(X) int f(X = 0)\n"
|
|
|
|
"foo(int \n"
|
|
|
|
" a);\n";
|
|
|
|
expected =
|
|
|
|
"# 1 \"<stdin>\"\n"
|
|
|
|
"\n"
|
|
|
|
"# expansion begin 28,3 ~3 2:4 3:4 ~3\n"
|
|
|
|
"int f(int a = 0)\n"
|
|
|
|
"# expansion end\n"
|
|
|
|
"# 3 \"<stdin>\"\n"
|
|
|
|
" ;\n";
|
|
|
|
QTest::newRow("case 4") << original << expected;
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Preprocessor::multitokens_argument()
|
|
|
|
{
|
|
|
|
compare_input_output();
|
2012-03-16 15:16:06 +01:00
|
|
|
}
|
|
|
|
|
2012-04-02 08:46:56 +02:00
|
|
|
void tst_Preprocessor::objmacro_expanding_as_fnmacro_notification()
|
|
|
|
{
|
|
|
|
QByteArray output;
|
|
|
|
Environment env;
|
|
|
|
MockClient client(&env, &output);
|
|
|
|
|
|
|
|
Preprocessor preprocess(&client, &env);
|
2012-04-19 10:35:49 +02:00
|
|
|
QByteArray preprocessed = preprocess.run(QLatin1String("<stdin>"),
|
2012-04-02 08:46:56 +02:00
|
|
|
QByteArray("\n#define bar(a,b) a + b"
|
|
|
|
"\n#define foo bar"
|
|
|
|
"\nfoo(1, 2)\n"));
|
|
|
|
|
|
|
|
QVERIFY(client.expandedMacros() == (QList<QByteArray>() << QByteArray("foo")));
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Preprocessor::macro_arguments_notificatin()
|
|
|
|
{
|
|
|
|
QByteArray output;
|
|
|
|
Environment env;
|
|
|
|
MockClient client(&env, &output);
|
|
|
|
|
|
|
|
Preprocessor preprocess(&client, &env);
|
2012-04-19 10:35:49 +02:00
|
|
|
QByteArray preprocessed = preprocess.run(QLatin1String("<stdin>"),
|
2012-04-02 08:46:56 +02:00
|
|
|
QByteArray("\n#define foo(a,b) a + b"
|
|
|
|
"\n#define arg(a) a"
|
|
|
|
"\n#define value 2"
|
|
|
|
"\nfoo(arg(1), value)\n"));
|
|
|
|
|
|
|
|
QVERIFY(client.expandedMacros() == (QList<QByteArray>() << QByteArray("foo")
|
|
|
|
<< QByteArray("arg")
|
|
|
|
<< QByteArray("value")));
|
|
|
|
}
|
|
|
|
|
2009-03-03 16:32:08 +01:00
|
|
|
void tst_Preprocessor::unfinished_function_like_macro_call()
|
|
|
|
{
|
|
|
|
Client *client = 0; // no client.
|
|
|
|
Environment env;
|
|
|
|
|
|
|
|
Preprocessor preprocess(client, &env);
|
2012-04-19 10:35:49 +02:00
|
|
|
QByteArray preprocessed = preprocess.run(QLatin1String("<stdin>"),
|
C++: Core changes in preprocessing
Summary of most relevant items:
- Preprocessor output format change. No more gen true/false. Instead
a more intuitive and natural expansion (like from a real compiler) is
performed directly corresponding to the macro invocation. Notice that
information about the generated tokens is not lost, because it's now
embedded in the expansion section header (in terms of lines and columns
as explained in the code). In addition the location on where the macro
expansion happens is also documented for future use.
- Fix line control directives and associated token line numbers.
This was not detected in tests cases because some of them were
actually wrong: Within expansions the line information was being
considered as originally computed in the macro definition, while
the desired and expected for Creator's reporting mechanism (just
like regular compilers) is the line from the expanded version
of the tokens.
- Do not allow for eager expansion. This was previously being done
inside define directives. However, it's not allowed and might
lead to incorrect results, since the argument substitution should
only happen upon the macro invocation (and following nested ones).
At least GCC and clang are consistent with that. See test case
tst_Preprocessor:dont_eagerly_expand for a detailed explanation.
- Revive the 'expanded' token flag. This is used to mark every token
that originates from a macro expansion. Notice, however, that
expanded tokens are not necessarily generated tokens (although
every generated token is a expanded token). Expanded tokens that
are not generated are those which are still considered by our
code model features, since they are visible on the editor. The
translation unit is smart enough to calculate line/column position
for such tokens based on the information from the expansion section
header.
- How expansions are tracked has also changed. Now, we simply add
two surrounding marker tokens to each "top-level" expansion
sequence. There is an enumeration that control expansion states.
Also, no "previous" token is kept around.
- Preprocessor client methods suffered a change in signature so
they now receive the line number of the action in question as
a paramater. Previously such line could be retrieved by the client
implementation by accessing the environment line. However, this
is not reliable because we try to avoid synchronization of the
output/environment lines in order to avoid unnecessary output,
while expanding macros or handling preprocessor directives.
- Although macros are not expanded during define directives (as
mentioned above) the preprocessor client is now "notified"
when it sees a macro. This is to allow usage tracking.
- Other small stuff.
This is all in one patch because the fixes are a consequence
of the change in preprocessing control.
Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
|
|
|
QByteArray("\n"
|
|
|
|
"#define foo(a,b) a + b\n"
|
|
|
|
"foo(1, 2\n"));
|
|
|
|
QByteArray expected__("# 1 \"<stdin>\"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"# expansion begin 24,3 3:4 ~1 3:7\n"
|
|
|
|
"1 + 2\n"
|
|
|
|
"# expansion end\n"
|
|
|
|
"# 4 \"<stdin>\"\n");
|
|
|
|
|
2012-03-30 13:01:32 +02:00
|
|
|
// DUMP_OUTPUT(preprocessed);
|
2012-03-26 15:18:01 +02:00
|
|
|
QCOMPARE(preprocessed, expected__);
|
2009-03-03 16:32:08 +01:00
|
|
|
}
|
|
|
|
|
2010-02-10 11:04:31 +01:00
|
|
|
void tst_Preprocessor::nasty_macro_expansion()
|
|
|
|
{
|
|
|
|
QByteArray input("\n"
|
|
|
|
"#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))\n"
|
|
|
|
"#define is_power_of_two(x) ( !((x) & ((x)-1)) )\n"
|
|
|
|
"#define low_bit_mask(x) ( ((x)-1) & ~(x) )\n"
|
|
|
|
"#define is_valid_mask(x) is_power_of_two(1LU + (x) + low_bit_mask(x))\n"
|
|
|
|
"#define compile_ffs2(__x) \\\n"
|
|
|
|
" __builtin_choose_expr(((__x) & 0x1), 0, 1)\n"
|
|
|
|
"#define compile_ffs4(__x) \\\n"
|
|
|
|
" __builtin_choose_expr(((__x) & 0x3), \\\n"
|
|
|
|
" (compile_ffs2((__x))), \\\n"
|
|
|
|
" (compile_ffs2((__x) >> 2) + 2))\n"
|
|
|
|
"#define compile_ffs8(__x) \\\n"
|
|
|
|
" __builtin_choose_expr(((__x) & 0xf), \\\n"
|
|
|
|
" (compile_ffs4((__x))), \\\n"
|
|
|
|
" (compile_ffs4((__x) >> 4) + 4))\n"
|
|
|
|
"#define compile_ffs16(__x) \\\n"
|
|
|
|
" __builtin_choose_expr(((__x) & 0xff), \\\n"
|
|
|
|
" (compile_ffs8((__x))), \\\n"
|
|
|
|
" (compile_ffs8((__x) >> 8) + 8))\n"
|
|
|
|
"#define compile_ffs32(__x) \\\n"
|
|
|
|
" __builtin_choose_expr(((__x) & 0xffff), \\\n"
|
|
|
|
" (compile_ffs16((__x))), \\\n"
|
|
|
|
" (compile_ffs16((__x) >> 16) + 16))\n"
|
|
|
|
"#define FIELD_CHECK(__mask, __type) \\\n"
|
|
|
|
" BUILD_BUG_ON(!(__mask) || \\\n"
|
|
|
|
" !is_valid_mask(__mask) || \\\n"
|
|
|
|
" (__mask) != (__type)(__mask)) \\\n"
|
|
|
|
"\n"
|
|
|
|
"#define FIELD32(__mask) \\\n"
|
|
|
|
"({ \\\n"
|
|
|
|
" FIELD_CHECK(__mask, u32); \\\n"
|
|
|
|
" (struct rt2x00_field32) { \\\n"
|
|
|
|
" compile_ffs32(__mask), (__mask) \\\n"
|
|
|
|
" }; \\\n"
|
|
|
|
"})\n"
|
|
|
|
"#define BBPCSR 0x00f0\n"
|
|
|
|
"#define BBPCSR_BUSY FIELD32(0x00008000)\n"
|
|
|
|
"#define WAIT_FOR_BBP(__dev, __reg) \\\n"
|
|
|
|
" rt2x00pci_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg))\n"
|
|
|
|
"if (WAIT_FOR_BBP(rt2x00dev, ®)) {}\n"
|
|
|
|
);
|
|
|
|
|
|
|
|
Client *client = 0; // no client.
|
|
|
|
Environment env;
|
|
|
|
|
|
|
|
Preprocessor preprocess(client, &env);
|
2012-04-19 10:35:49 +02:00
|
|
|
QByteArray preprocessed = preprocess.run(QLatin1String("<stdin>"), input);
|
2010-02-10 11:04:31 +01:00
|
|
|
|
|
|
|
QVERIFY(!preprocessed.contains("FIELD32"));
|
|
|
|
}
|
|
|
|
|
C++: Core changes in preprocessing
Summary of most relevant items:
- Preprocessor output format change. No more gen true/false. Instead
a more intuitive and natural expansion (like from a real compiler) is
performed directly corresponding to the macro invocation. Notice that
information about the generated tokens is not lost, because it's now
embedded in the expansion section header (in terms of lines and columns
as explained in the code). In addition the location on where the macro
expansion happens is also documented for future use.
- Fix line control directives and associated token line numbers.
This was not detected in tests cases because some of them were
actually wrong: Within expansions the line information was being
considered as originally computed in the macro definition, while
the desired and expected for Creator's reporting mechanism (just
like regular compilers) is the line from the expanded version
of the tokens.
- Do not allow for eager expansion. This was previously being done
inside define directives. However, it's not allowed and might
lead to incorrect results, since the argument substitution should
only happen upon the macro invocation (and following nested ones).
At least GCC and clang are consistent with that. See test case
tst_Preprocessor:dont_eagerly_expand for a detailed explanation.
- Revive the 'expanded' token flag. This is used to mark every token
that originates from a macro expansion. Notice, however, that
expanded tokens are not necessarily generated tokens (although
every generated token is a expanded token). Expanded tokens that
are not generated are those which are still considered by our
code model features, since they are visible on the editor. The
translation unit is smart enough to calculate line/column position
for such tokens based on the information from the expansion section
header.
- How expansions are tracked has also changed. Now, we simply add
two surrounding marker tokens to each "top-level" expansion
sequence. There is an enumeration that control expansion states.
Also, no "previous" token is kept around.
- Preprocessor client methods suffered a change in signature so
they now receive the line number of the action in question as
a paramater. Previously such line could be retrieved by the client
implementation by accessing the environment line. However, this
is not reliable because we try to avoid synchronization of the
output/environment lines in order to avoid unnecessary output,
while expanding macros or handling preprocessor directives.
- Although macros are not expanded during define directives (as
mentioned above) the preprocessor client is now "notified"
when it sees a macro. This is to allow usage tracking.
- Other small stuff.
This is all in one patch because the fixes are a consequence
of the change in preprocessing control.
Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
|
|
|
void tst_Preprocessor::glib_attribute()
|
2012-02-24 13:06:21 +01:00
|
|
|
{
|
|
|
|
Environment env;
|
C++: Core changes in preprocessing
Summary of most relevant items:
- Preprocessor output format change. No more gen true/false. Instead
a more intuitive and natural expansion (like from a real compiler) is
performed directly corresponding to the macro invocation. Notice that
information about the generated tokens is not lost, because it's now
embedded in the expansion section header (in terms of lines and columns
as explained in the code). In addition the location on where the macro
expansion happens is also documented for future use.
- Fix line control directives and associated token line numbers.
This was not detected in tests cases because some of them were
actually wrong: Within expansions the line information was being
considered as originally computed in the macro definition, while
the desired and expected for Creator's reporting mechanism (just
like regular compilers) is the line from the expanded version
of the tokens.
- Do not allow for eager expansion. This was previously being done
inside define directives. However, it's not allowed and might
lead to incorrect results, since the argument substitution should
only happen upon the macro invocation (and following nested ones).
At least GCC and clang are consistent with that. See test case
tst_Preprocessor:dont_eagerly_expand for a detailed explanation.
- Revive the 'expanded' token flag. This is used to mark every token
that originates from a macro expansion. Notice, however, that
expanded tokens are not necessarily generated tokens (although
every generated token is a expanded token). Expanded tokens that
are not generated are those which are still considered by our
code model features, since they are visible on the editor. The
translation unit is smart enough to calculate line/column position
for such tokens based on the information from the expansion section
header.
- How expansions are tracked has also changed. Now, we simply add
two surrounding marker tokens to each "top-level" expansion
sequence. There is an enumeration that control expansion states.
Also, no "previous" token is kept around.
- Preprocessor client methods suffered a change in signature so
they now receive the line number of the action in question as
a paramater. Previously such line could be retrieved by the client
implementation by accessing the environment line. However, this
is not reliable because we try to avoid synchronization of the
output/environment lines in order to avoid unnecessary output,
while expanding macros or handling preprocessor directives.
- Although macros are not expanded during define directives (as
mentioned above) the preprocessor client is now "notified"
when it sees a macro. This is to allow usage tracking.
- Other small stuff.
This is all in one patch because the fixes are a consequence
of the change in preprocessing control.
Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
|
|
|
Preprocessor preprocess(0, &env);
|
2012-04-19 10:35:49 +02:00
|
|
|
QByteArray preprocessed = preprocess.run(
|
2012-02-24 13:06:21 +01:00
|
|
|
QLatin1String("<stdin>"),
|
|
|
|
QByteArray("\n"
|
|
|
|
"# define _GLIBCXX_VISIBILITY(V) __attribute__ ((__visibility__ (#V)))\n"
|
|
|
|
"namespace std _GLIBCXX_VISIBILITY(default) {\n"
|
|
|
|
"}\n"
|
|
|
|
));
|
C++: Core changes in preprocessing
Summary of most relevant items:
- Preprocessor output format change. No more gen true/false. Instead
a more intuitive and natural expansion (like from a real compiler) is
performed directly corresponding to the macro invocation. Notice that
information about the generated tokens is not lost, because it's now
embedded in the expansion section header (in terms of lines and columns
as explained in the code). In addition the location on where the macro
expansion happens is also documented for future use.
- Fix line control directives and associated token line numbers.
This was not detected in tests cases because some of them were
actually wrong: Within expansions the line information was being
considered as originally computed in the macro definition, while
the desired and expected for Creator's reporting mechanism (just
like regular compilers) is the line from the expanded version
of the tokens.
- Do not allow for eager expansion. This was previously being done
inside define directives. However, it's not allowed and might
lead to incorrect results, since the argument substitution should
only happen upon the macro invocation (and following nested ones).
At least GCC and clang are consistent with that. See test case
tst_Preprocessor:dont_eagerly_expand for a detailed explanation.
- Revive the 'expanded' token flag. This is used to mark every token
that originates from a macro expansion. Notice, however, that
expanded tokens are not necessarily generated tokens (although
every generated token is a expanded token). Expanded tokens that
are not generated are those which are still considered by our
code model features, since they are visible on the editor. The
translation unit is smart enough to calculate line/column position
for such tokens based on the information from the expansion section
header.
- How expansions are tracked has also changed. Now, we simply add
two surrounding marker tokens to each "top-level" expansion
sequence. There is an enumeration that control expansion states.
Also, no "previous" token is kept around.
- Preprocessor client methods suffered a change in signature so
they now receive the line number of the action in question as
a paramater. Previously such line could be retrieved by the client
implementation by accessing the environment line. However, this
is not reliable because we try to avoid synchronization of the
output/environment lines in order to avoid unnecessary output,
while expanding macros or handling preprocessor directives.
- Although macros are not expanded during define directives (as
mentioned above) the preprocessor client is now "notified"
when it sees a macro. This is to allow usage tracking.
- Other small stuff.
This is all in one patch because the fixes are a consequence
of the change in preprocessing control.
Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
|
|
|
const QByteArray result____ =
|
|
|
|
"# 1 \"<stdin>\"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
2012-03-26 15:18:01 +02:00
|
|
|
"namespace std\n"
|
C++: Core changes in preprocessing
Summary of most relevant items:
- Preprocessor output format change. No more gen true/false. Instead
a more intuitive and natural expansion (like from a real compiler) is
performed directly corresponding to the macro invocation. Notice that
information about the generated tokens is not lost, because it's now
embedded in the expansion section header (in terms of lines and columns
as explained in the code). In addition the location on where the macro
expansion happens is also documented for future use.
- Fix line control directives and associated token line numbers.
This was not detected in tests cases because some of them were
actually wrong: Within expansions the line information was being
considered as originally computed in the macro definition, while
the desired and expected for Creator's reporting mechanism (just
like regular compilers) is the line from the expanded version
of the tokens.
- Do not allow for eager expansion. This was previously being done
inside define directives. However, it's not allowed and might
lead to incorrect results, since the argument substitution should
only happen upon the macro invocation (and following nested ones).
At least GCC and clang are consistent with that. See test case
tst_Preprocessor:dont_eagerly_expand for a detailed explanation.
- Revive the 'expanded' token flag. This is used to mark every token
that originates from a macro expansion. Notice, however, that
expanded tokens are not necessarily generated tokens (although
every generated token is a expanded token). Expanded tokens that
are not generated are those which are still considered by our
code model features, since they are visible on the editor. The
translation unit is smart enough to calculate line/column position
for such tokens based on the information from the expansion section
header.
- How expansions are tracked has also changed. Now, we simply add
two surrounding marker tokens to each "top-level" expansion
sequence. There is an enumeration that control expansion states.
Also, no "previous" token is kept around.
- Preprocessor client methods suffered a change in signature so
they now receive the line number of the action in question as
a paramater. Previously such line could be retrieved by the client
implementation by accessing the environment line. However, this
is not reliable because we try to avoid synchronization of the
output/environment lines in order to avoid unnecessary output,
while expanding macros or handling preprocessor directives.
- Although macros are not expanded during define directives (as
mentioned above) the preprocessor client is now "notified"
when it sees a macro. This is to allow usage tracking.
- Other small stuff.
This is all in one patch because the fixes are a consequence
of the change in preprocessing control.
Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
|
|
|
"# expansion begin 85,19 ~9\n"
|
|
|
|
"__attribute__ ((__visibility__ (\"default\")))\n"
|
|
|
|
"# expansion end\n"
|
2012-03-13 11:50:56 +01:00
|
|
|
"# 3 \"<stdin>\"\n"
|
|
|
|
" {\n"
|
2012-03-26 15:18:01 +02:00
|
|
|
"}\n";
|
|
|
|
|
2012-03-30 13:01:32 +02:00
|
|
|
// DUMP_OUTPUT(preprocessed);
|
2012-03-26 15:18:01 +02:00
|
|
|
QCOMPARE(preprocessed, result____);
|
|
|
|
}
|
|
|
|
|
C++: Core changes in preprocessing
Summary of most relevant items:
- Preprocessor output format change. No more gen true/false. Instead
a more intuitive and natural expansion (like from a real compiler) is
performed directly corresponding to the macro invocation. Notice that
information about the generated tokens is not lost, because it's now
embedded in the expansion section header (in terms of lines and columns
as explained in the code). In addition the location on where the macro
expansion happens is also documented for future use.
- Fix line control directives and associated token line numbers.
This was not detected in tests cases because some of them were
actually wrong: Within expansions the line information was being
considered as originally computed in the macro definition, while
the desired and expected for Creator's reporting mechanism (just
like regular compilers) is the line from the expanded version
of the tokens.
- Do not allow for eager expansion. This was previously being done
inside define directives. However, it's not allowed and might
lead to incorrect results, since the argument substitution should
only happen upon the macro invocation (and following nested ones).
At least GCC and clang are consistent with that. See test case
tst_Preprocessor:dont_eagerly_expand for a detailed explanation.
- Revive the 'expanded' token flag. This is used to mark every token
that originates from a macro expansion. Notice, however, that
expanded tokens are not necessarily generated tokens (although
every generated token is a expanded token). Expanded tokens that
are not generated are those which are still considered by our
code model features, since they are visible on the editor. The
translation unit is smart enough to calculate line/column position
for such tokens based on the information from the expansion section
header.
- How expansions are tracked has also changed. Now, we simply add
two surrounding marker tokens to each "top-level" expansion
sequence. There is an enumeration that control expansion states.
Also, no "previous" token is kept around.
- Preprocessor client methods suffered a change in signature so
they now receive the line number of the action in question as
a paramater. Previously such line could be retrieved by the client
implementation by accessing the environment line. However, this
is not reliable because we try to avoid synchronization of the
output/environment lines in order to avoid unnecessary output,
while expanding macros or handling preprocessor directives.
- Although macros are not expanded during define directives (as
mentioned above) the preprocessor client is now "notified"
when it sees a macro. This is to allow usage tracking.
- Other small stuff.
This is all in one patch because the fixes are a consequence
of the change in preprocessing control.
Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
|
|
|
void tst_Preprocessor::builtin__FILE__()
|
2012-03-26 15:18:01 +02:00
|
|
|
{
|
|
|
|
Client *client = 0; // no client.
|
|
|
|
Environment env;
|
|
|
|
|
|
|
|
Preprocessor preprocess(client, &env);
|
2012-04-19 10:35:49 +02:00
|
|
|
QByteArray preprocessed = preprocess.run(
|
2012-03-26 15:18:01 +02:00
|
|
|
QLatin1String("some-file.c"),
|
|
|
|
QByteArray("const char *f = __FILE__\n"
|
|
|
|
));
|
|
|
|
const QByteArray result____ =
|
2012-03-30 13:01:32 +02:00
|
|
|
"# 1 \"some-file.c\"\n"
|
C++: Core changes in preprocessing
Summary of most relevant items:
- Preprocessor output format change. No more gen true/false. Instead
a more intuitive and natural expansion (like from a real compiler) is
performed directly corresponding to the macro invocation. Notice that
information about the generated tokens is not lost, because it's now
embedded in the expansion section header (in terms of lines and columns
as explained in the code). In addition the location on where the macro
expansion happens is also documented for future use.
- Fix line control directives and associated token line numbers.
This was not detected in tests cases because some of them were
actually wrong: Within expansions the line information was being
considered as originally computed in the macro definition, while
the desired and expected for Creator's reporting mechanism (just
like regular compilers) is the line from the expanded version
of the tokens.
- Do not allow for eager expansion. This was previously being done
inside define directives. However, it's not allowed and might
lead to incorrect results, since the argument substitution should
only happen upon the macro invocation (and following nested ones).
At least GCC and clang are consistent with that. See test case
tst_Preprocessor:dont_eagerly_expand for a detailed explanation.
- Revive the 'expanded' token flag. This is used to mark every token
that originates from a macro expansion. Notice, however, that
expanded tokens are not necessarily generated tokens (although
every generated token is a expanded token). Expanded tokens that
are not generated are those which are still considered by our
code model features, since they are visible on the editor. The
translation unit is smart enough to calculate line/column position
for such tokens based on the information from the expansion section
header.
- How expansions are tracked has also changed. Now, we simply add
two surrounding marker tokens to each "top-level" expansion
sequence. There is an enumeration that control expansion states.
Also, no "previous" token is kept around.
- Preprocessor client methods suffered a change in signature so
they now receive the line number of the action in question as
a paramater. Previously such line could be retrieved by the client
implementation by accessing the environment line. However, this
is not reliable because we try to avoid synchronization of the
output/environment lines in order to avoid unnecessary output,
while expanding macros or handling preprocessor directives.
- Although macros are not expanded during define directives (as
mentioned above) the preprocessor client is now "notified"
when it sees a macro. This is to allow usage tracking.
- Other small stuff.
This is all in one patch because the fixes are a consequence
of the change in preprocessing control.
Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
|
|
|
"const char *f = \"some-file.c\"\n";
|
|
|
|
|
2012-03-26 15:18:01 +02:00
|
|
|
QCOMPARE(preprocessed, result____);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Preprocessor::comparisons_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QString>("infile");
|
|
|
|
QTest::addColumn<QString>("outfile");
|
|
|
|
QTest::addColumn<QString>("errorfile");
|
|
|
|
|
|
|
|
QTest::newRow("do nothing") << "noPP.1.cpp" << "noPP.1.cpp" << "";
|
C++: Core changes in preprocessing
Summary of most relevant items:
- Preprocessor output format change. No more gen true/false. Instead
a more intuitive and natural expansion (like from a real compiler) is
performed directly corresponding to the macro invocation. Notice that
information about the generated tokens is not lost, because it's now
embedded in the expansion section header (in terms of lines and columns
as explained in the code). In addition the location on where the macro
expansion happens is also documented for future use.
- Fix line control directives and associated token line numbers.
This was not detected in tests cases because some of them were
actually wrong: Within expansions the line information was being
considered as originally computed in the macro definition, while
the desired and expected for Creator's reporting mechanism (just
like regular compilers) is the line from the expanded version
of the tokens.
- Do not allow for eager expansion. This was previously being done
inside define directives. However, it's not allowed and might
lead to incorrect results, since the argument substitution should
only happen upon the macro invocation (and following nested ones).
At least GCC and clang are consistent with that. See test case
tst_Preprocessor:dont_eagerly_expand for a detailed explanation.
- Revive the 'expanded' token flag. This is used to mark every token
that originates from a macro expansion. Notice, however, that
expanded tokens are not necessarily generated tokens (although
every generated token is a expanded token). Expanded tokens that
are not generated are those which are still considered by our
code model features, since they are visible on the editor. The
translation unit is smart enough to calculate line/column position
for such tokens based on the information from the expansion section
header.
- How expansions are tracked has also changed. Now, we simply add
two surrounding marker tokens to each "top-level" expansion
sequence. There is an enumeration that control expansion states.
Also, no "previous" token is kept around.
- Preprocessor client methods suffered a change in signature so
they now receive the line number of the action in question as
a paramater. Previously such line could be retrieved by the client
implementation by accessing the environment line. However, this
is not reliable because we try to avoid synchronization of the
output/environment lines in order to avoid unnecessary output,
while expanding macros or handling preprocessor directives.
- Although macros are not expanded during define directives (as
mentioned above) the preprocessor client is now "notified"
when it sees a macro. This is to allow usage tracking.
- Other small stuff.
This is all in one patch because the fixes are a consequence
of the change in preprocessing control.
Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
|
|
|
QTest::newRow("no PP 2") << "noPP.2.cpp" << "noPP.2.cpp" << "";
|
2012-04-24 18:29:09 +02:00
|
|
|
QTest::newRow("identifier-expansion 1")
|
|
|
|
<< "identifier-expansion.1.cpp" << "identifier-expansion.1.out.cpp" << "";
|
|
|
|
QTest::newRow("identifier-expansion 2")
|
|
|
|
<< "identifier-expansion.2.cpp" << "identifier-expansion.2.out.cpp" << "";
|
|
|
|
QTest::newRow("identifier-expansion 3")
|
|
|
|
<< "identifier-expansion.3.cpp" << "identifier-expansion.3.out.cpp" << "";
|
|
|
|
QTest::newRow("identifier-expansion 4")
|
|
|
|
<< "identifier-expansion.4.cpp" << "identifier-expansion.4.out.cpp" << "";
|
|
|
|
QTest::newRow("identifier-expansion 5")
|
|
|
|
<< "identifier-expansion.5.cpp" << "identifier-expansion.5.out.cpp" << "";
|
2012-04-27 16:46:57 +02:00
|
|
|
QTest::newRow("reserved 1")
|
|
|
|
<< "reserved.1.cpp" << "reserved.1.out.cpp" << "";
|
|
|
|
QTest::newRow("recursive 1")
|
|
|
|
<< "recursive.1.cpp" << "recursive.1.out.cpp" << "";
|
|
|
|
QTest::newRow("macro_pounder_fn")
|
|
|
|
<< "macro_pounder_fn.c" << "" << "";
|
|
|
|
QTest::newRow("macro_expand")
|
|
|
|
<< "macro_expand.c" << "macro_expand.out.c" << "";
|
2012-05-15 17:39:13 +02:00
|
|
|
QTest::newRow("macro_expand_1")
|
|
|
|
<< "macro_expand_1.cpp" << "macro_expand_1.out.cpp" << "";
|
2012-04-27 16:46:57 +02:00
|
|
|
QTest::newRow("macro-test")
|
|
|
|
<< "macro-test.cpp" << "macro-test.out.cpp" << "";
|
|
|
|
QTest::newRow("empty-macro")
|
|
|
|
<< "empty-macro.cpp" << "empty-macro.out.cpp" << "";
|
|
|
|
QTest::newRow("empty-macro 2")
|
|
|
|
<< "empty-macro.2.cpp" << "empty-macro.2.out.cpp" << "";
|
2012-04-27 17:11:48 +02:00
|
|
|
QTest::newRow("poundpound 1")
|
|
|
|
<< "poundpound.1.cpp" << "poundpound.1.out.cpp" << "";
|
2012-03-26 15:18:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Preprocessor::comparisons()
|
|
|
|
{
|
|
|
|
QFETCH(QString, infile);
|
|
|
|
QFETCH(QString, outfile);
|
|
|
|
QFETCH(QString, errorfile);
|
|
|
|
|
|
|
|
QByteArray errors;
|
2012-03-30 13:01:32 +02:00
|
|
|
QByteArray preprocessed = preprocess(infile, &errors, infile == outfile);
|
2012-03-26 15:18:01 +02:00
|
|
|
|
C++: Core changes in preprocessing
Summary of most relevant items:
- Preprocessor output format change. No more gen true/false. Instead
a more intuitive and natural expansion (like from a real compiler) is
performed directly corresponding to the macro invocation. Notice that
information about the generated tokens is not lost, because it's now
embedded in the expansion section header (in terms of lines and columns
as explained in the code). In addition the location on where the macro
expansion happens is also documented for future use.
- Fix line control directives and associated token line numbers.
This was not detected in tests cases because some of them were
actually wrong: Within expansions the line information was being
considered as originally computed in the macro definition, while
the desired and expected for Creator's reporting mechanism (just
like regular compilers) is the line from the expanded version
of the tokens.
- Do not allow for eager expansion. This was previously being done
inside define directives. However, it's not allowed and might
lead to incorrect results, since the argument substitution should
only happen upon the macro invocation (and following nested ones).
At least GCC and clang are consistent with that. See test case
tst_Preprocessor:dont_eagerly_expand for a detailed explanation.
- Revive the 'expanded' token flag. This is used to mark every token
that originates from a macro expansion. Notice, however, that
expanded tokens are not necessarily generated tokens (although
every generated token is a expanded token). Expanded tokens that
are not generated are those which are still considered by our
code model features, since they are visible on the editor. The
translation unit is smart enough to calculate line/column position
for such tokens based on the information from the expansion section
header.
- How expansions are tracked has also changed. Now, we simply add
two surrounding marker tokens to each "top-level" expansion
sequence. There is an enumeration that control expansion states.
Also, no "previous" token is kept around.
- Preprocessor client methods suffered a change in signature so
they now receive the line number of the action in question as
a paramater. Previously such line could be retrieved by the client
implementation by accessing the environment line. However, this
is not reliable because we try to avoid synchronization of the
output/environment lines in order to avoid unnecessary output,
while expanding macros or handling preprocessor directives.
- Although macros are not expanded during define directives (as
mentioned above) the preprocessor client is now "notified"
when it sees a macro. This is to allow usage tracking.
- Other small stuff.
This is all in one patch because the fixes are a consequence
of the change in preprocessing control.
Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
|
|
|
|
2012-04-27 16:46:57 +02:00
|
|
|
// DUMP_OUTPUT(preprocessed);
|
2012-03-26 15:18:01 +02:00
|
|
|
|
|
|
|
if (!outfile.isEmpty()) {
|
2012-04-27 16:46:57 +02:00
|
|
|
// These weird underscores are here to make the name as long as
|
|
|
|
// "preprocessed", so the QCOMPARE error messages are nicely aligned.
|
|
|
|
QByteArray output____ = loadSource("data/" + outfile);
|
2012-03-26 15:18:01 +02:00
|
|
|
// QCOMPARE(preprocessed, output____);
|
2012-04-27 16:46:57 +02:00
|
|
|
QCOMPARE(QString::fromUtf8(preprocessed.constData()),
|
|
|
|
QString::fromUtf8(output____.constData()));
|
2012-03-26 15:18:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!errorfile.isEmpty()) {
|
2012-04-27 16:46:57 +02:00
|
|
|
QByteArray errorFileContents = loadSource("data/" + errorfile);
|
|
|
|
QCOMPARE(QString::fromUtf8(errors.constData()),
|
|
|
|
QString::fromUtf8(errorFileContents.constData()));
|
2012-03-26 15:18:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Preprocessor::blockSkipping()
|
|
|
|
{
|
|
|
|
QByteArray output;
|
|
|
|
Environment env;
|
|
|
|
MockClient client(&env, &output);
|
|
|
|
Preprocessor pp(&client, &env);
|
2012-04-19 10:35:49 +02:00
|
|
|
/*QByteArray preprocessed =*/ pp.run(
|
2012-03-26 15:18:01 +02:00
|
|
|
QLatin1String("<stdin>"),
|
|
|
|
QByteArray("#if 0\n"
|
|
|
|
"\n"
|
|
|
|
"int yes;\n"
|
|
|
|
"\n"
|
|
|
|
"#elif 0\n"
|
|
|
|
"\n"
|
|
|
|
"int no;\n"
|
|
|
|
"\n"
|
|
|
|
"#else // foobar\n"
|
|
|
|
"\n"
|
|
|
|
"void also_not;\n"
|
|
|
|
"\n"
|
|
|
|
"#endif\n"
|
|
|
|
));
|
2012-03-13 11:50:56 +01:00
|
|
|
|
2012-03-26 15:18:01 +02:00
|
|
|
QList<MockClient::Block> blocks = client.skippedBlocks();
|
|
|
|
QCOMPARE(blocks.size(), 1);
|
|
|
|
MockClient::Block b = blocks.at(0);
|
|
|
|
QCOMPARE(b.start, 6U);
|
|
|
|
QCOMPARE(b.end, 34U);
|
2012-02-24 13:06:21 +01:00
|
|
|
}
|
|
|
|
|
2012-03-29 17:14:42 +02:00
|
|
|
void tst_Preprocessor::includes_1()
|
|
|
|
{
|
|
|
|
QByteArray output;
|
|
|
|
Environment env;
|
|
|
|
MockClient client(&env, &output);
|
|
|
|
Preprocessor pp(&client, &env);
|
2012-04-19 10:35:49 +02:00
|
|
|
/*QByteArray preprocessed =*/ pp.run(
|
2012-03-29 17:14:42 +02:00
|
|
|
QLatin1String("<stdin>"),
|
|
|
|
QByteArray("#define FOO <foo.h>\n"
|
|
|
|
"#define BAR \"bar.h\"\n"
|
|
|
|
"\n"
|
|
|
|
"#include FOO\n"
|
|
|
|
"#include BAR\n"
|
|
|
|
"\n"
|
|
|
|
"#include <zoo.h>\n"
|
|
|
|
"#include \"mooze.h\"\n"
|
|
|
|
));
|
|
|
|
|
|
|
|
QList<Include> incs = client.recordedIncludes();
|
|
|
|
// qDebug()<<incs;
|
|
|
|
QCOMPARE(incs.size(), 4);
|
|
|
|
QCOMPARE(incs.at(0).fileName, QLatin1String("foo.h"));
|
|
|
|
QCOMPARE(incs.at(0).type, Client::IncludeGlobal);
|
|
|
|
QCOMPARE(incs.at(0).line, 4U);
|
|
|
|
QCOMPARE(incs.at(1).fileName, QLatin1String("bar.h"));
|
|
|
|
QCOMPARE(incs.at(1).type, Client::IncludeLocal);
|
|
|
|
QCOMPARE(incs.at(1).line, 5U);
|
|
|
|
QCOMPARE(incs.at(2).fileName, QLatin1String("zoo.h"));
|
|
|
|
QCOMPARE(incs.at(2).type, Client::IncludeGlobal);
|
|
|
|
QCOMPARE(incs.at(2).line, 7U);
|
|
|
|
QCOMPARE(incs.at(3).fileName, QLatin1String("mooze.h"));
|
|
|
|
QCOMPARE(incs.at(3).type, Client::IncludeLocal);
|
|
|
|
QCOMPARE(incs.at(3).line, 8U);
|
|
|
|
}
|
|
|
|
|
2012-04-19 15:19:38 +02:00
|
|
|
void tst_Preprocessor::defined()
|
|
|
|
{
|
|
|
|
QFETCH(bool, xdefined);
|
|
|
|
QFETCH(bool, ydefined);
|
|
|
|
QFETCH(QString, input);
|
|
|
|
QByteArray output;
|
|
|
|
Environment env;
|
|
|
|
MockClient client(&env, &output);
|
|
|
|
Preprocessor pp(&client, &env);
|
|
|
|
pp.run(QLatin1String("<stdin>"), input.toLatin1(), false, true);
|
|
|
|
QList<QByteArray> expected;
|
|
|
|
if (xdefined)
|
|
|
|
expected.append("X");
|
|
|
|
if (ydefined)
|
|
|
|
expected.append("Y");
|
|
|
|
if (client.definedMacros() != expected)
|
|
|
|
qWarning() << "\nSource: " << input.replace('\n', " ");
|
|
|
|
QCOMPARE(client.definedMacros(), expected);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Preprocessor::defined_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<bool>("xdefined");
|
|
|
|
QTest::addColumn<bool>("ydefined");
|
|
|
|
QTest::addColumn<QString>("input");
|
|
|
|
|
|
|
|
QTest::newRow("1a") << true << true <<
|
|
|
|
"#define X\n#if defined(X)\n#define Y\n#endif";
|
|
|
|
QTest::newRow("1b") << true << true <<
|
|
|
|
"#define X\n#if defined X \n#define Y\n#endif";
|
|
|
|
QTest::newRow("1c") << true << true <<
|
|
|
|
"#define X\n#ifdef X \n#define Y\n#endif";
|
|
|
|
|
|
|
|
QTest::newRow("2a") << false << false <<
|
|
|
|
"#if defined(X)\n#define Y\n#endif";
|
|
|
|
QTest::newRow("2b") << false << false <<
|
|
|
|
"#if defined X \n#define Y\n#endif";
|
|
|
|
QTest::newRow("2c") << false << false <<
|
|
|
|
"#ifdef X \n#define Y\n#endif";
|
|
|
|
|
|
|
|
QTest::newRow("3a") << true << false <<
|
|
|
|
"#define X\n#if !defined(X)\n#define Y\n#endif";
|
|
|
|
QTest::newRow("3b") << true << false <<
|
|
|
|
"#define X\n#if !defined X \n#define Y\n#endif";
|
|
|
|
QTest::newRow("3c") << true << false <<
|
|
|
|
"#define X\n#ifndef X \n#define Y\n#endif";
|
|
|
|
|
|
|
|
QTest::newRow("4a") << false << true <<
|
|
|
|
"#if !defined(X)\n#define Y\n#endif";
|
|
|
|
QTest::newRow("4b") << false << true <<
|
|
|
|
"#if !defined X \n#define Y\n#endif";
|
|
|
|
QTest::newRow("4c") << false << true <<
|
|
|
|
"#ifndef X \n#define Y\n#endif";
|
2012-04-24 18:50:22 +02:00
|
|
|
|
|
|
|
QTest::newRow("5a") << false << false <<
|
|
|
|
"#if !defined(X) && (defined(Y))\n"
|
|
|
|
"#define X\n"
|
|
|
|
"#endif\n";
|
|
|
|
QTest::newRow("5b") << false << false <<
|
|
|
|
"#if !defined(X) && defined(Y)\n"
|
|
|
|
"#define X\n"
|
|
|
|
"#endif\n";
|
|
|
|
QTest::newRow("5c") << false << false <<
|
|
|
|
"#if !defined(X) && 0"
|
|
|
|
"#define X\n"
|
|
|
|
"#endif\n";
|
|
|
|
QTest::newRow("5d") << false << false <<
|
|
|
|
"#if (!defined(X)) && defined(Y)\n"
|
|
|
|
"#define X\n"
|
|
|
|
"#endif\n";
|
|
|
|
QTest::newRow("5d") << false << false <<
|
|
|
|
"#if (define(Y))\n"
|
|
|
|
"#define X\n"
|
|
|
|
"#endif\n";
|
2012-04-25 12:30:48 +02:00
|
|
|
|
|
|
|
QTest::newRow("6a") << true << true <<
|
|
|
|
"#define X 0x040500\n"
|
|
|
|
"#if X > 0x040000\n"
|
|
|
|
"#define Y 1\n"
|
|
|
|
"#endif\n";
|
|
|
|
QTest::newRow("6b") << true << true <<
|
|
|
|
"#define X 0x040500\n"
|
|
|
|
"#if X >= 0x040000\n"
|
|
|
|
"#define Y 1\n"
|
|
|
|
"#endif\n";
|
|
|
|
QTest::newRow("6c") << true << false <<
|
|
|
|
"#define X 0x040500\n"
|
|
|
|
"#if X == 0x040000\n"
|
|
|
|
"#define Y 1\n"
|
|
|
|
"#endif\n";
|
|
|
|
QTest::newRow("6d") << true << true <<
|
|
|
|
"#define X 0x040500\n"
|
|
|
|
"#if X == 0x040500\n"
|
|
|
|
"#define Y 1\n"
|
|
|
|
"#endif\n";
|
|
|
|
QTest::newRow("6e") << true << false <<
|
|
|
|
"#define X 0x040500\n"
|
|
|
|
"#if X < 0x040000\n"
|
|
|
|
"#define Y 1\n"
|
|
|
|
"#endif\n";
|
|
|
|
QTest::newRow("6f") << true << false <<
|
|
|
|
"#define X 0x040500\n"
|
|
|
|
"#if X <= 0x040000\n"
|
|
|
|
"#define Y 1\n"
|
|
|
|
"#endif\n";
|
2012-05-29 14:33:56 +02:00
|
|
|
|
|
|
|
QTest::newRow("incomplete defined 1") << true << true <<
|
|
|
|
"#define X 0x040500\n"
|
|
|
|
"#if defined(X\n"
|
|
|
|
"#define Y 1\n"
|
|
|
|
"#endif\n";
|
|
|
|
QTest::newRow("incomplete defined 2") << false << false <<
|
|
|
|
"#if defined(X\n"
|
|
|
|
"#define Y 1\n"
|
|
|
|
"#endif\n";
|
|
|
|
QTest::newRow("complete defined 1") << true << true <<
|
|
|
|
"#define X 0x040500\n"
|
|
|
|
"#if defined(X )\n"
|
|
|
|
"#define Y 1\n"
|
|
|
|
"#endif\n";
|
|
|
|
QTest::newRow("complete defined 2") << true << true <<
|
|
|
|
"#define X 0x040500\n"
|
|
|
|
"#if defined(X/*xxx*/)\n"
|
|
|
|
"#define Y 1\n"
|
|
|
|
"#endif\n";
|
2012-04-19 15:19:38 +02:00
|
|
|
}
|
|
|
|
|
C++: Core changes in preprocessing
Summary of most relevant items:
- Preprocessor output format change. No more gen true/false. Instead
a more intuitive and natural expansion (like from a real compiler) is
performed directly corresponding to the macro invocation. Notice that
information about the generated tokens is not lost, because it's now
embedded in the expansion section header (in terms of lines and columns
as explained in the code). In addition the location on where the macro
expansion happens is also documented for future use.
- Fix line control directives and associated token line numbers.
This was not detected in tests cases because some of them were
actually wrong: Within expansions the line information was being
considered as originally computed in the macro definition, while
the desired and expected for Creator's reporting mechanism (just
like regular compilers) is the line from the expanded version
of the tokens.
- Do not allow for eager expansion. This was previously being done
inside define directives. However, it's not allowed and might
lead to incorrect results, since the argument substitution should
only happen upon the macro invocation (and following nested ones).
At least GCC and clang are consistent with that. See test case
tst_Preprocessor:dont_eagerly_expand for a detailed explanation.
- Revive the 'expanded' token flag. This is used to mark every token
that originates from a macro expansion. Notice, however, that
expanded tokens are not necessarily generated tokens (although
every generated token is a expanded token). Expanded tokens that
are not generated are those which are still considered by our
code model features, since they are visible on the editor. The
translation unit is smart enough to calculate line/column position
for such tokens based on the information from the expansion section
header.
- How expansions are tracked has also changed. Now, we simply add
two surrounding marker tokens to each "top-level" expansion
sequence. There is an enumeration that control expansion states.
Also, no "previous" token is kept around.
- Preprocessor client methods suffered a change in signature so
they now receive the line number of the action in question as
a paramater. Previously such line could be retrieved by the client
implementation by accessing the environment line. However, this
is not reliable because we try to avoid synchronization of the
output/environment lines in order to avoid unnecessary output,
while expanding macros or handling preprocessor directives.
- Although macros are not expanded during define directives (as
mentioned above) the preprocessor client is now "notified"
when it sees a macro. This is to allow usage tracking.
- Other small stuff.
This is all in one patch because the fixes are a consequence
of the change in preprocessing control.
Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
|
|
|
void tst_Preprocessor::dont_eagerly_expand_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QByteArray>("input");
|
|
|
|
QTest::addColumn<QByteArray>("output");
|
|
|
|
|
|
|
|
QByteArray original;
|
|
|
|
QByteArray expected;
|
|
|
|
|
|
|
|
// Expansion must be processed upon invocation of the macro. Therefore a particular
|
|
|
|
// identifier within a define must not be expanded (in the case it matches an
|
|
|
|
// already known macro) during the processor directive handling, but only when
|
|
|
|
// it's actually "used". Naturally, if it's still not replaced after an invocation
|
|
|
|
// it should then be expanded. This is consistent with clang and gcc for example.
|
|
|
|
|
|
|
|
original = "#define T int\n"
|
|
|
|
"#define FOO(T) T\n"
|
|
|
|
"FOO(double)\n";
|
|
|
|
expected =
|
|
|
|
"# 1 \"<stdin>\"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"# expansion begin 31,3 3:4\n"
|
|
|
|
"double\n"
|
|
|
|
"# expansion end\n"
|
|
|
|
"# 4 \"<stdin>\"\n";
|
|
|
|
QTest::newRow("case 1") << original << expected;
|
|
|
|
|
|
|
|
original = "#define T int\n"
|
|
|
|
"#define FOO(X) T\n"
|
|
|
|
"FOO(double)\n";
|
|
|
|
expected =
|
|
|
|
"# 1 \"<stdin>\"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"# expansion begin 31,3 ~1\n"
|
|
|
|
"int\n"
|
|
|
|
"# expansion end\n"
|
|
|
|
"# 4 \"<stdin>\"\n";
|
|
|
|
QTest::newRow("case 2") << original << expected;
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Preprocessor::dont_eagerly_expand()
|
|
|
|
{
|
|
|
|
compare_input_output();
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Preprocessor::comments_within()
|
|
|
|
{
|
|
|
|
compare_input_output();
|
|
|
|
}
|
|
|
|
void tst_Preprocessor::comments_within_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QByteArray>("input");
|
|
|
|
QTest::addColumn<QByteArray>("output");
|
|
|
|
|
|
|
|
QByteArray original;
|
|
|
|
QByteArray expected;
|
|
|
|
|
|
|
|
original = "#define FOO int x;\n"
|
|
|
|
"\n"
|
|
|
|
" // comment\n"
|
|
|
|
" // comment\n"
|
|
|
|
" // comment\n"
|
|
|
|
" // comment\n"
|
|
|
|
"FOO\n"
|
|
|
|
"x = 10\n";
|
|
|
|
expected =
|
|
|
|
"# 1 \"<stdin>\"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"# expansion begin 76,3 ~3\n"
|
|
|
|
"int x;\n"
|
|
|
|
"# expansion end\n"
|
|
|
|
"# 8 \"<stdin>\"\n"
|
|
|
|
"x = 10\n";
|
|
|
|
QTest::newRow("case 1") << original << expected;
|
|
|
|
|
|
|
|
|
|
|
|
original = "#define FOO int x;\n"
|
|
|
|
"\n"
|
|
|
|
" /* comment\n"
|
|
|
|
" comment\n"
|
|
|
|
" comment\n"
|
|
|
|
" comment */\n"
|
|
|
|
"FOO\n"
|
|
|
|
"x = 10\n";
|
|
|
|
expected =
|
|
|
|
"# 1 \"<stdin>\"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"# expansion begin 79,3 ~3\n"
|
|
|
|
"int x;\n"
|
|
|
|
"# expansion end\n"
|
|
|
|
"# 8 \"<stdin>\"\n"
|
|
|
|
"x = 10\n";
|
|
|
|
QTest::newRow("case 2") << original << expected;
|
|
|
|
|
|
|
|
|
|
|
|
original = "#define FOO int x;\n"
|
|
|
|
"\n"
|
|
|
|
" // comment\n"
|
|
|
|
" // comment\n"
|
|
|
|
" // comment\n"
|
|
|
|
" // comment\n"
|
|
|
|
"FOO\n"
|
|
|
|
"// test\n"
|
|
|
|
"// test again\n"
|
|
|
|
"x = 10\n";
|
|
|
|
expected =
|
|
|
|
"# 1 \"<stdin>\"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"# expansion begin 76,3 ~3\n"
|
|
|
|
"int x;\n"
|
|
|
|
"# expansion end\n"
|
|
|
|
"# 10 \"<stdin>\"\n"
|
|
|
|
"x = 10\n";
|
|
|
|
QTest::newRow("case 3") << original << expected;
|
|
|
|
|
|
|
|
|
|
|
|
original = "#define FOO int x;\n"
|
|
|
|
"\n"
|
|
|
|
" /* comment\n"
|
|
|
|
" comment\n"
|
|
|
|
" comment\n"
|
|
|
|
" comment */\n"
|
|
|
|
"FOO\n"
|
|
|
|
"/* \n"
|
|
|
|
"*/\n"
|
|
|
|
"x = 10\n";
|
|
|
|
expected =
|
|
|
|
"# 1 \"<stdin>\"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"# expansion begin 79,3 ~3\n"
|
|
|
|
"int x;\n"
|
|
|
|
"# expansion end\n"
|
|
|
|
"# 10 \"<stdin>\"\n"
|
|
|
|
"x = 10\n";
|
|
|
|
QTest::newRow("case 4") << original << expected;
|
2012-08-15 16:06:22 +02:00
|
|
|
|
|
|
|
original = "#define FOO(x, y) { (void)x; (void)y; }\n"
|
|
|
|
"\n"
|
|
|
|
"void foo() {\n"
|
|
|
|
" FOO(10,\n"
|
|
|
|
" //comment\n"
|
|
|
|
" 12\n"
|
|
|
|
"}\n";
|
|
|
|
expected =
|
|
|
|
"# 1 \"<stdin>\"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"void foo() {\n"
|
|
|
|
"# expansion begin 57,3 ~4 4:7 ~4 6:7 7:0 ~2\n"
|
|
|
|
"{ (void)10; (void)12}; }\n"
|
|
|
|
"# expansion end\n"
|
|
|
|
"# 8 \"<stdin>\"\n";
|
|
|
|
QTest::newRow("case 5") << original << expected;
|
|
|
|
|
|
|
|
original = "#define FOO(x, y) { (void)x; (void)y; }\n"
|
|
|
|
"\n"
|
|
|
|
"void foo() {\n"
|
|
|
|
" FOO(10,\n"
|
|
|
|
" //tricky*/comment\n"
|
|
|
|
" 12\n"
|
|
|
|
"}\n";
|
|
|
|
expected =
|
|
|
|
"# 1 \"<stdin>\"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"void foo() {\n"
|
|
|
|
"# expansion begin 57,3 ~4 4:7 ~4 6:7 7:0 ~2\n"
|
|
|
|
"{ (void)10; (void)12}; }\n"
|
|
|
|
"# expansion end\n"
|
|
|
|
"# 8 \"<stdin>\"\n";
|
|
|
|
QTest::newRow("case 6") << original << expected;
|
2012-09-05 15:16:47 +02:00
|
|
|
|
|
|
|
original =
|
|
|
|
"#define FOO 0 //coment\n"
|
|
|
|
"#define BAR (1 == FOO)\n"
|
|
|
|
"void foo() {\n"
|
|
|
|
" if (BAR) {}\n"
|
|
|
|
"}\n";
|
|
|
|
expected =
|
|
|
|
"# 1 \"<stdin>\"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"void foo() {\n"
|
|
|
|
" if (\n"
|
|
|
|
"# expansion begin 67,3 ~5\n"
|
|
|
|
"(1 == 0)\n"
|
|
|
|
"# expansion end\n"
|
|
|
|
"# 4 \"<stdin>\"\n"
|
|
|
|
" ) {}\n"
|
|
|
|
"}\n";
|
|
|
|
QTest::newRow("case 7") << original << expected;
|
C++: Core changes in preprocessing
Summary of most relevant items:
- Preprocessor output format change. No more gen true/false. Instead
a more intuitive and natural expansion (like from a real compiler) is
performed directly corresponding to the macro invocation. Notice that
information about the generated tokens is not lost, because it's now
embedded in the expansion section header (in terms of lines and columns
as explained in the code). In addition the location on where the macro
expansion happens is also documented for future use.
- Fix line control directives and associated token line numbers.
This was not detected in tests cases because some of them were
actually wrong: Within expansions the line information was being
considered as originally computed in the macro definition, while
the desired and expected for Creator's reporting mechanism (just
like regular compilers) is the line from the expanded version
of the tokens.
- Do not allow for eager expansion. This was previously being done
inside define directives. However, it's not allowed and might
lead to incorrect results, since the argument substitution should
only happen upon the macro invocation (and following nested ones).
At least GCC and clang are consistent with that. See test case
tst_Preprocessor:dont_eagerly_expand for a detailed explanation.
- Revive the 'expanded' token flag. This is used to mark every token
that originates from a macro expansion. Notice, however, that
expanded tokens are not necessarily generated tokens (although
every generated token is a expanded token). Expanded tokens that
are not generated are those which are still considered by our
code model features, since they are visible on the editor. The
translation unit is smart enough to calculate line/column position
for such tokens based on the information from the expansion section
header.
- How expansions are tracked has also changed. Now, we simply add
two surrounding marker tokens to each "top-level" expansion
sequence. There is an enumeration that control expansion states.
Also, no "previous" token is kept around.
- Preprocessor client methods suffered a change in signature so
they now receive the line number of the action in question as
a paramater. Previously such line could be retrieved by the client
implementation by accessing the environment line. However, this
is not reliable because we try to avoid synchronization of the
output/environment lines in order to avoid unnecessary output,
while expanding macros or handling preprocessor directives.
- Although macros are not expanded during define directives (as
mentioned above) the preprocessor client is now "notified"
when it sees a macro. This is to allow usage tracking.
- Other small stuff.
This is all in one patch because the fixes are a consequence
of the change in preprocessing control.
Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
|
|
|
}
|
|
|
|
|
2012-08-07 10:47:38 +02:00
|
|
|
void tst_Preprocessor::comments_within2()
|
|
|
|
{
|
|
|
|
compare_input_output(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Preprocessor::comments_within2_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QByteArray>("input");
|
|
|
|
QTest::addColumn<QByteArray>("output");
|
|
|
|
|
|
|
|
QByteArray original;
|
|
|
|
QByteArray expected;
|
|
|
|
|
|
|
|
original = "#define FOO int x;\n"
|
|
|
|
"\n"
|
|
|
|
" // comment\n"
|
|
|
|
" // comment\n"
|
|
|
|
" // comment\n"
|
|
|
|
" // comment\n"
|
|
|
|
"FOO\n"
|
|
|
|
"x = 10\n";
|
|
|
|
expected =
|
|
|
|
"# 1 \"<stdin>\"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
" // comment\n"
|
|
|
|
" // comment\n"
|
|
|
|
" // comment\n"
|
|
|
|
" // comment\n"
|
|
|
|
"# expansion begin 76,3 ~3\n"
|
|
|
|
"int x;\n"
|
|
|
|
"# expansion end\n"
|
|
|
|
"# 8 \"<stdin>\"\n"
|
|
|
|
"x = 10\n";
|
|
|
|
QTest::newRow("case 1") << original << expected;
|
|
|
|
|
|
|
|
|
|
|
|
original = "#define FOO int x;\n"
|
|
|
|
"\n"
|
|
|
|
" /* comment\n"
|
|
|
|
" comment\n"
|
|
|
|
" comment\n"
|
|
|
|
" comment */\n"
|
|
|
|
"FOO\n"
|
|
|
|
"x = 10\n";
|
|
|
|
expected =
|
|
|
|
"# 1 \"<stdin>\"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
" /* comment\n"
|
|
|
|
" comment\n"
|
|
|
|
" comment\n"
|
|
|
|
" comment */\n"
|
|
|
|
"# expansion begin 79,3 ~3\n"
|
|
|
|
"int x;\n"
|
|
|
|
"# expansion end\n"
|
|
|
|
"# 8 \"<stdin>\"\n"
|
|
|
|
"x = 10\n";
|
|
|
|
QTest::newRow("case 2") << original << expected;
|
|
|
|
|
|
|
|
|
|
|
|
original = "#define FOO int x;\n"
|
|
|
|
"\n"
|
|
|
|
" // comment\n"
|
|
|
|
" // comment\n"
|
|
|
|
" // comment\n"
|
|
|
|
" // comment\n"
|
|
|
|
"FOO\n"
|
|
|
|
"// test\n"
|
|
|
|
"// test again\n"
|
|
|
|
"x = 10\n";
|
|
|
|
expected =
|
|
|
|
"# 1 \"<stdin>\"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
" // comment\n"
|
|
|
|
" // comment\n"
|
|
|
|
" // comment\n"
|
|
|
|
" // comment\n"
|
|
|
|
"# expansion begin 76,3 ~3\n"
|
|
|
|
"int x;\n"
|
|
|
|
"# expansion end\n"
|
|
|
|
"# 8 \"<stdin>\"\n"
|
|
|
|
"// test\n"
|
|
|
|
"// test again\n"
|
|
|
|
"x = 10\n";
|
|
|
|
QTest::newRow("case 3") << original << expected;
|
|
|
|
|
|
|
|
|
|
|
|
original = "#define FOO int x;\n"
|
|
|
|
"\n"
|
|
|
|
"void foo() { /* comment\n"
|
|
|
|
" comment\n"
|
|
|
|
" comment\n"
|
|
|
|
" comment */\n"
|
|
|
|
"FOO\n"
|
|
|
|
"/* \n"
|
|
|
|
"*/\n"
|
|
|
|
"x = 10\n";
|
|
|
|
expected =
|
|
|
|
"# 1 \"<stdin>\"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"void foo() { /* comment\n"
|
|
|
|
" comment\n"
|
|
|
|
" comment\n"
|
|
|
|
" comment */\n"
|
|
|
|
"# expansion begin 91,3 ~3\n"
|
|
|
|
"int x;\n"
|
|
|
|
"# expansion end\n"
|
|
|
|
"# 8 \"<stdin>\"\n"
|
|
|
|
"/* \n"
|
|
|
|
"*/\n"
|
|
|
|
"x = 10\n";
|
|
|
|
QTest::newRow("case 4") << original << expected;
|
2012-08-15 16:06:22 +02:00
|
|
|
|
|
|
|
|
|
|
|
original = "#define FOO(x, y) { (void)x; (void)y; }\n"
|
|
|
|
"\n"
|
|
|
|
"void foo() {\n"
|
|
|
|
" FOO(10,\n"
|
|
|
|
" //comment\n"
|
|
|
|
" 12\n"
|
|
|
|
"}\n";
|
|
|
|
expected =
|
|
|
|
"# 1 \"<stdin>\"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"void foo() {\n"
|
|
|
|
"# expansion begin 57,3 ~4 4:7 ~5 6:7 7:0 ~2\n"
|
|
|
|
"{ (void)10; (void)/*comment*/ 12}; }\n"
|
|
|
|
"# expansion end\n"
|
|
|
|
"# 8 \"<stdin>\"\n";
|
|
|
|
QTest::newRow("case 5") << original << expected;
|
|
|
|
|
|
|
|
original = "#define FOO(x, y) { (void)x; (void)y; }\n"
|
|
|
|
"\n"
|
|
|
|
"void foo() {\n"
|
|
|
|
" FOO(10,\n"
|
|
|
|
" //tricky*/comment\n"
|
|
|
|
" 12\n"
|
|
|
|
"}\n";
|
|
|
|
expected =
|
|
|
|
"# 1 \"<stdin>\"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"void foo() {\n"
|
|
|
|
"# expansion begin 57,3 ~4 4:7 ~5 6:7 7:0 ~2\n"
|
|
|
|
"{ (void)10; (void)/*tricky*|comment*/ 12}; }\n"
|
|
|
|
"# expansion end\n"
|
|
|
|
"# 8 \"<stdin>\"\n";
|
|
|
|
QTest::newRow("case 6") << original << expected;
|
2012-09-05 15:16:47 +02:00
|
|
|
|
|
|
|
original =
|
|
|
|
"#define FOO 0 //coment\n"
|
|
|
|
"#define BAR (1 == FOO)\n"
|
|
|
|
"void foo() {\n"
|
|
|
|
" if (BAR) {}\n"
|
|
|
|
"}\n";
|
|
|
|
expected =
|
|
|
|
"# 1 \"<stdin>\"\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"void foo() {\n"
|
|
|
|
" if (\n"
|
|
|
|
"# expansion begin 67,3 ~5\n"
|
|
|
|
"(1 == 0)\n"
|
|
|
|
"# expansion end\n"
|
|
|
|
"# 4 \"<stdin>\"\n"
|
|
|
|
" ) {}\n"
|
|
|
|
"}\n";
|
|
|
|
QTest::newRow("case 7") << original << expected;
|
2012-08-07 10:47:38 +02:00
|
|
|
}
|
|
|
|
|
2012-08-20 23:11:34 +02:00
|
|
|
void tst_Preprocessor::multiline_strings()
|
|
|
|
{
|
|
|
|
compare_input_output();
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Preprocessor::multiline_strings_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QByteArray>("input");
|
|
|
|
QTest::addColumn<QByteArray>("output");
|
|
|
|
|
|
|
|
QByteArray original;
|
|
|
|
QByteArray expected;
|
|
|
|
|
|
|
|
original = "const char *s = \"abc\\\n"
|
|
|
|
"xyz\";\n";
|
|
|
|
expected = "# 1 \"<stdin>\"\n"
|
|
|
|
"const char *s = \"abc\\\n"
|
|
|
|
"xyz\";\n";
|
|
|
|
QTest::newRow("case 1") << original << expected;
|
|
|
|
}
|
|
|
|
|
2012-08-29 13:21:22 +02:00
|
|
|
void tst_Preprocessor::skip_unknown_directives()
|
|
|
|
{
|
|
|
|
compare_input_output();
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Preprocessor::skip_unknown_directives_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QByteArray>("input");
|
|
|
|
QTest::addColumn<QByteArray>("output");
|
|
|
|
|
|
|
|
QByteArray original;
|
|
|
|
QByteArray expected;
|
|
|
|
|
|
|
|
// We should skip "weird" things when preprocessing. Particularly useful when we preprocess
|
|
|
|
// a particular expression from a document which has already been processed.
|
|
|
|
|
|
|
|
original = "# foo\n"
|
|
|
|
"# 10 \"file.cpp\"\n"
|
|
|
|
"# ()\n"
|
|
|
|
"#\n";
|
|
|
|
expected = "# 1 \"<stdin>\"\n";
|
|
|
|
QTest::newRow("case 1") << original << expected;
|
|
|
|
}
|
|
|
|
|
2012-08-07 10:47:38 +02:00
|
|
|
void tst_Preprocessor::compare_input_output(bool keepComments)
|
C++: Core changes in preprocessing
Summary of most relevant items:
- Preprocessor output format change. No more gen true/false. Instead
a more intuitive and natural expansion (like from a real compiler) is
performed directly corresponding to the macro invocation. Notice that
information about the generated tokens is not lost, because it's now
embedded in the expansion section header (in terms of lines and columns
as explained in the code). In addition the location on where the macro
expansion happens is also documented for future use.
- Fix line control directives and associated token line numbers.
This was not detected in tests cases because some of them were
actually wrong: Within expansions the line information was being
considered as originally computed in the macro definition, while
the desired and expected for Creator's reporting mechanism (just
like regular compilers) is the line from the expanded version
of the tokens.
- Do not allow for eager expansion. This was previously being done
inside define directives. However, it's not allowed and might
lead to incorrect results, since the argument substitution should
only happen upon the macro invocation (and following nested ones).
At least GCC and clang are consistent with that. See test case
tst_Preprocessor:dont_eagerly_expand for a detailed explanation.
- Revive the 'expanded' token flag. This is used to mark every token
that originates from a macro expansion. Notice, however, that
expanded tokens are not necessarily generated tokens (although
every generated token is a expanded token). Expanded tokens that
are not generated are those which are still considered by our
code model features, since they are visible on the editor. The
translation unit is smart enough to calculate line/column position
for such tokens based on the information from the expansion section
header.
- How expansions are tracked has also changed. Now, we simply add
two surrounding marker tokens to each "top-level" expansion
sequence. There is an enumeration that control expansion states.
Also, no "previous" token is kept around.
- Preprocessor client methods suffered a change in signature so
they now receive the line number of the action in question as
a paramater. Previously such line could be retrieved by the client
implementation by accessing the environment line. However, this
is not reliable because we try to avoid synchronization of the
output/environment lines in order to avoid unnecessary output,
while expanding macros or handling preprocessor directives.
- Although macros are not expanded during define directives (as
mentioned above) the preprocessor client is now "notified"
when it sees a macro. This is to allow usage tracking.
- Other small stuff.
This is all in one patch because the fixes are a consequence
of the change in preprocessing control.
Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
|
|
|
{
|
|
|
|
QFETCH(QByteArray, input);
|
|
|
|
QFETCH(QByteArray, output);
|
|
|
|
|
|
|
|
Environment env;
|
|
|
|
Preprocessor preprocess(0, &env);
|
2012-08-07 10:47:38 +02:00
|
|
|
preprocess.setKeepComments(keepComments);
|
C++: Core changes in preprocessing
Summary of most relevant items:
- Preprocessor output format change. No more gen true/false. Instead
a more intuitive and natural expansion (like from a real compiler) is
performed directly corresponding to the macro invocation. Notice that
information about the generated tokens is not lost, because it's now
embedded in the expansion section header (in terms of lines and columns
as explained in the code). In addition the location on where the macro
expansion happens is also documented for future use.
- Fix line control directives and associated token line numbers.
This was not detected in tests cases because some of them were
actually wrong: Within expansions the line information was being
considered as originally computed in the macro definition, while
the desired and expected for Creator's reporting mechanism (just
like regular compilers) is the line from the expanded version
of the tokens.
- Do not allow for eager expansion. This was previously being done
inside define directives. However, it's not allowed and might
lead to incorrect results, since the argument substitution should
only happen upon the macro invocation (and following nested ones).
At least GCC and clang are consistent with that. See test case
tst_Preprocessor:dont_eagerly_expand for a detailed explanation.
- Revive the 'expanded' token flag. This is used to mark every token
that originates from a macro expansion. Notice, however, that
expanded tokens are not necessarily generated tokens (although
every generated token is a expanded token). Expanded tokens that
are not generated are those which are still considered by our
code model features, since they are visible on the editor. The
translation unit is smart enough to calculate line/column position
for such tokens based on the information from the expansion section
header.
- How expansions are tracked has also changed. Now, we simply add
two surrounding marker tokens to each "top-level" expansion
sequence. There is an enumeration that control expansion states.
Also, no "previous" token is kept around.
- Preprocessor client methods suffered a change in signature so
they now receive the line number of the action in question as
a paramater. Previously such line could be retrieved by the client
implementation by accessing the environment line. However, this
is not reliable because we try to avoid synchronization of the
output/environment lines in order to avoid unnecessary output,
while expanding macros or handling preprocessor directives.
- Although macros are not expanded during define directives (as
mentioned above) the preprocessor client is now "notified"
when it sees a macro. This is to allow usage tracking.
- Other small stuff.
This is all in one patch because the fixes are a consequence
of the change in preprocessing control.
Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
|
|
|
QByteArray prep = preprocess.run(QLatin1String("<stdin>"), input);
|
|
|
|
QCOMPARE(output, prep);
|
|
|
|
}
|
|
|
|
|
2009-03-02 11:30:43 +01:00
|
|
|
QTEST_APPLESS_MAIN(tst_Preprocessor)
|
2012-04-19 15:19:38 +02:00
|
|
|
|
2009-03-02 11:30:43 +01:00
|
|
|
#include "tst_preprocessor.moc"
|