forked from qt-creator/qt-creator
C++: Track macro argument reference even when empty
Change-Id: I6d226b4e42f94ebee41d012050c5109895f0c432 Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
@@ -801,16 +801,20 @@ bool Preprocessor::handleIdentifier(PPToken *tk)
|
|||||||
|
|
||||||
if (m_client && !idTk.generated()) {
|
if (m_client && !idTk.generated()) {
|
||||||
// Bundle each token sequence into a macro argument "reference" for notification.
|
// Bundle each token sequence into a macro argument "reference" for notification.
|
||||||
|
// Even empty ones, which are not necessarily important on its own, but for the matter
|
||||||
|
// of couting their number - such as in foo(,)
|
||||||
QVector<MacroArgumentReference> argRefs;
|
QVector<MacroArgumentReference> argRefs;
|
||||||
for (int i = 0; i < allArgTks.size(); ++i) {
|
for (int i = 0; i < allArgTks.size(); ++i) {
|
||||||
const QVector<PPToken> &argTks = allArgTks.at(i);
|
const QVector<PPToken> &argTks = allArgTks.at(i);
|
||||||
if (argTks.isEmpty())
|
if (argTks.isEmpty()) {
|
||||||
continue;
|
argRefs.push_back(MacroArgumentReference());
|
||||||
|
} else {
|
||||||
|
|
||||||
argRefs.push_back(
|
argRefs.push_back(MacroArgumentReference(
|
||||||
MacroArgumentReference(
|
m_state.m_offsetRef + argTks.first().begin(),
|
||||||
m_state.m_offsetRef + argTks.first().begin(),
|
argTks.last().begin() + argTks.last().length()
|
||||||
argTks.last().begin() + argTks.last().length() - argTks.first().begin()));
|
- argTks.first().begin()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_client->startExpandingMacro(m_state.m_offsetRef + idTk.offset, *macro, macroNameRef,
|
m_client->startExpandingMacro(m_state.m_offsetRef + idTk.offset, *macro, macroNameRef,
|
||||||
|
|||||||
@@ -120,12 +120,13 @@ public:
|
|||||||
virtual void startExpandingMacro(unsigned offset,
|
virtual void startExpandingMacro(unsigned offset,
|
||||||
const Macro ¯o,
|
const Macro ¯o,
|
||||||
const ByteArrayRef &originalText,
|
const ByteArrayRef &originalText,
|
||||||
const QVector<MacroArgumentReference> &/*actuals*/
|
const QVector<MacroArgumentReference> &actuals
|
||||||
= QVector<MacroArgumentReference>())
|
= QVector<MacroArgumentReference>())
|
||||||
{
|
{
|
||||||
m_expandedMacros.append(QByteArray(originalText.start(), originalText.length()));
|
m_expandedMacros.append(QByteArray(originalText.start(), originalText.length()));
|
||||||
m_expandedMacrosOffset.append(offset);
|
m_expandedMacrosOffset.append(offset);
|
||||||
m_macroUsesLine[macro.name()].append(m_env->currentLine);
|
m_macroUsesLine[macro.name()].append(m_env->currentLine);
|
||||||
|
m_macroArgsCount.append(actuals.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void stopExpandingMacro(unsigned /*offset*/, const Macro &/*macro*/) {}
|
virtual void stopExpandingMacro(unsigned /*offset*/, const Macro &/*macro*/) {}
|
||||||
@@ -232,6 +233,9 @@ public:
|
|||||||
QHash<QByteArray, QList<unsigned> > macroUsesLine() const
|
QHash<QByteArray, QList<unsigned> > macroUsesLine() const
|
||||||
{ return m_macroUsesLine; }
|
{ return m_macroUsesLine; }
|
||||||
|
|
||||||
|
const QList<int> macroArgsCount() const
|
||||||
|
{ return m_macroArgsCount; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Environment *m_env;
|
Environment *m_env;
|
||||||
QByteArray *m_output;
|
QByteArray *m_output;
|
||||||
@@ -245,6 +249,7 @@ private:
|
|||||||
QList<QByteArray> m_definedMacros;
|
QList<QByteArray> m_definedMacros;
|
||||||
QList<unsigned> m_definedMacrosLine;
|
QList<unsigned> m_definedMacrosLine;
|
||||||
QHash<QByteArray, QList<unsigned> > m_macroUsesLine;
|
QHash<QByteArray, QList<unsigned> > m_macroUsesLine;
|
||||||
|
QList<int> m_macroArgsCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
@@ -305,7 +310,8 @@ private slots:
|
|||||||
|
|
||||||
void va_args();
|
void va_args();
|
||||||
void named_va_args();
|
void named_va_args();
|
||||||
void first_empty_macro_arg();
|
void empty_macro_args();
|
||||||
|
void macro_args_count();
|
||||||
void invalid_param_count();
|
void invalid_param_count();
|
||||||
void objmacro_expanding_as_fnmacro_notification();
|
void objmacro_expanding_as_fnmacro_notification();
|
||||||
void macro_definition_lineno();
|
void macro_definition_lineno();
|
||||||
@@ -386,7 +392,7 @@ void tst_Preprocessor::named_va_args()
|
|||||||
QCOMPARE(simplified(preprocessed), QString("int f();int f(int a);int f(int a,int b);"));
|
QCOMPARE(simplified(preprocessed), QString("int f();int f(int a);int f(int a,int b);"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_Preprocessor::first_empty_macro_arg()
|
void tst_Preprocessor::empty_macro_args()
|
||||||
{
|
{
|
||||||
Client *client = 0; // no client.
|
Client *client = 0; // no client.
|
||||||
Environment env;
|
Environment env;
|
||||||
@@ -396,12 +402,47 @@ void tst_Preprocessor::first_empty_macro_arg()
|
|||||||
"\n#define foo(a,b) a int b;"
|
"\n#define foo(a,b) a int b;"
|
||||||
"\nfoo(const,cVal)\n"
|
"\nfoo(const,cVal)\n"
|
||||||
"\nfoo(,Val)\n"
|
"\nfoo(,Val)\n"
|
||||||
"\nfoo( ,Val2)\n",
|
"\nfoo( ,Val2)\n"
|
||||||
|
"\nfoo(,)\n"
|
||||||
|
"\nfoo(, )\n",
|
||||||
true, false);
|
true, false);
|
||||||
|
|
||||||
preprocessed = preprocessed.simplified();
|
preprocessed = preprocessed.simplified();
|
||||||
// DUMP_OUTPUT(preprocessed);
|
// DUMP_OUTPUT(preprocessed);
|
||||||
QCOMPARE(simplified(preprocessed), QString("const int cVal;int Val;int Val2;"));
|
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)
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_Preprocessor::invalid_param_count()
|
void tst_Preprocessor::invalid_param_count()
|
||||||
|
|||||||
Reference in New Issue
Block a user