forked from qt-creator/qt-creator
C++: Better handling of arg count mismatch in macros
Do not expand function-like macros at all when there's a mismatch in the parameter/argument count. The report below raises the issue but its expected result is not correct. This would be the more appropriate fix. Task-number: QTCREATORBUG-7225 Change-Id: Ide8580faa7b724d3e8b396ec1f899cc5ca7f9e7e Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
@@ -793,7 +793,25 @@ bool Preprocessor::handleIdentifier(PPToken *tk)
|
|||||||
if (macro->isFunctionLike()) {
|
if (macro->isFunctionLike()) {
|
||||||
// Collect individual tokens that form the macro arguments.
|
// Collect individual tokens that form the macro arguments.
|
||||||
QVector<QVector<PPToken> > allArgTks;
|
QVector<QVector<PPToken> > allArgTks;
|
||||||
if (!collectActualArguments(tk, &allArgTks)) {
|
bool hasArgs = collectActualArguments(tk, &allArgTks);
|
||||||
|
|
||||||
|
// Check for matching parameter/argument count.
|
||||||
|
bool hasMatchingArgs = false;
|
||||||
|
if (hasArgs) {
|
||||||
|
const int expectedArgCount = macro->formals().size();
|
||||||
|
const int actualArgCount = allArgTks.size();
|
||||||
|
if (expectedArgCount == actualArgCount
|
||||||
|
|| (macro->isVariadic() && actualArgCount > expectedArgCount - 1)
|
||||||
|
// Handle '#define foo()' when invoked as 'foo()'
|
||||||
|
|| (expectedArgCount == 0
|
||||||
|
&& actualArgCount == 1
|
||||||
|
&& allArgTks.at(0).isEmpty())) {
|
||||||
|
hasMatchingArgs = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasArgs || !hasMatchingArgs) {
|
||||||
|
//### TODO: error message
|
||||||
pushToken(tk);
|
pushToken(tk);
|
||||||
*tk = idTk;
|
*tk = idTk;
|
||||||
return false;
|
return false;
|
||||||
@@ -872,12 +890,6 @@ bool Preprocessor::handleFunctionLikeMacro(PPToken *tk,
|
|||||||
int j = 0;
|
int j = 0;
|
||||||
for (; j < formals.size() && expanded.size() < MAX_TOKEN_EXPANSION_COUNT; ++j) {
|
for (; j < formals.size() && expanded.size() < MAX_TOKEN_EXPANSION_COUNT; ++j) {
|
||||||
if (formals[j] == id) {
|
if (formals[j] == id) {
|
||||||
if (actuals.size() <= j) {
|
|
||||||
// too few actual parameters
|
|
||||||
//### TODO: error message
|
|
||||||
goto exitNicely;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVector<PPToken> actualsForThisParam = actuals.at(j);
|
QVector<PPToken> actualsForThisParam = actuals.at(j);
|
||||||
if (id == "__VA_ARGS__" || (macro->isVariadic() && j + 1 == formals.size())) {
|
if (id == "__VA_ARGS__" || (macro->isVariadic() && j + 1 == formals.size())) {
|
||||||
unsigned lineno = 0;
|
unsigned lineno = 0;
|
||||||
@@ -929,7 +941,6 @@ bool Preprocessor::handleFunctionLikeMacro(PPToken *tk,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exitNicely:
|
|
||||||
pushToken(tk);
|
pushToken(tk);
|
||||||
if (addWhitespaceMarker) {
|
if (addWhitespaceMarker) {
|
||||||
PPToken forceWhitespacingToken;
|
PPToken forceWhitespacingToken;
|
||||||
|
@@ -300,10 +300,6 @@ protected:
|
|||||||
}
|
}
|
||||||
static QString simplified(QByteArray buf);
|
static QString simplified(QByteArray buf);
|
||||||
|
|
||||||
private /* not corrected yet */:
|
|
||||||
void param_expanding_as_multiple_params();
|
|
||||||
void macro_argument_expansion();
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void defined();
|
void defined();
|
||||||
void defined_data();
|
void defined_data();
|
||||||
@@ -447,49 +443,21 @@ void tst_Preprocessor::macro_args_count()
|
|||||||
|
|
||||||
void tst_Preprocessor::invalid_param_count()
|
void tst_Preprocessor::invalid_param_count()
|
||||||
{
|
{
|
||||||
Client *client = 0; // no client.
|
|
||||||
Environment env;
|
Environment env;
|
||||||
|
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);
|
||||||
|
|
||||||
Preprocessor preprocess(client, &env);
|
// Output is not that relevant but check that nothing triggered expansion.
|
||||||
// The following is illegal, but shouldn't crash the preprocessor.
|
QCOMPARE(client.macroArgsCount(), QList<int>());
|
||||||
// GCC says: 3:14: error: macro "foo" requires 2 arguments, but only 1 given
|
|
||||||
QByteArray preprocessed = preprocess.run(QLatin1String("<stdin>"),
|
|
||||||
"\n#define foo(a,b) int f(a,b);"
|
|
||||||
"\n#define ARGS(t) t a,t b"
|
|
||||||
"\nfoo(ARGS(int))",
|
|
||||||
true, false);
|
|
||||||
// do not verify the output: it's illegal, so anything might be outputted.
|
|
||||||
}
|
|
||||||
|
|
||||||
void tst_Preprocessor::param_expanding_as_multiple_params()
|
|
||||||
{
|
|
||||||
Client *client = 0; // no client.
|
|
||||||
Environment env;
|
|
||||||
|
|
||||||
Preprocessor preprocess(client, &env);
|
|
||||||
QByteArray preprocessed = preprocess.run(QLatin1String("<stdin>"),
|
|
||||||
"\n#define foo(a,b) int f(a,b);"
|
|
||||||
"\n#define ARGS(t) t a,t b"
|
|
||||||
"\nfoo(ARGS(int))",
|
|
||||||
false, true);
|
|
||||||
QCOMPARE(simplified(preprocessed), QString("int f(int a,int b);"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void tst_Preprocessor::macro_argument_expansion() //QTCREATORBUG-7225
|
|
||||||
{
|
|
||||||
Client *client = 0; // no client.
|
|
||||||
Environment env;
|
|
||||||
|
|
||||||
Preprocessor preprocess(client, &env);
|
|
||||||
QByteArray preprocessed = preprocess.run(QLatin1String("<stdin>"),
|
|
||||||
"\n#define BAR1 2,3,4"
|
|
||||||
"\n#define FOO1(a,b,c) a+b+c"
|
|
||||||
"\nvoid test2(){"
|
|
||||||
"\nint x=FOO1(BAR1);"
|
|
||||||
"\n}",
|
|
||||||
false, true);
|
|
||||||
QCOMPARE(simplified(preprocessed), QString("void test2(){int x=2+3+4;}"));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_Preprocessor::macro_uses()
|
void tst_Preprocessor::macro_uses()
|
||||||
|
Reference in New Issue
Block a user