Commit f978400a authored by Leandro Melo's avatar Leandro Melo Committed by hjk
Browse files

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: default avatarhjk <qthjk@ovi.com>
parent 7eaaab6e
......@@ -793,7 +793,25 @@ bool Preprocessor::handleIdentifier(PPToken *tk)
if (macro->isFunctionLike()) {
// Collect individual tokens that form the macro arguments.
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);
*tk = idTk;
return false;
......@@ -872,12 +890,6 @@ bool Preprocessor::handleFunctionLikeMacro(PPToken *tk,
int j = 0;
for (; j < formals.size() && expanded.size() < MAX_TOKEN_EXPANSION_COUNT; ++j) {
if (formals[j] == id) {
if (actuals.size() <= j) {
// too few actual parameters
//### TODO: error message
goto exitNicely;
}
QVector<PPToken> actualsForThisParam = actuals.at(j);
if (id == "__VA_ARGS__" || (macro->isVariadic() && j + 1 == formals.size())) {
unsigned lineno = 0;
......@@ -929,7 +941,6 @@ bool Preprocessor::handleFunctionLikeMacro(PPToken *tk,
}
}
exitNicely:
pushToken(tk);
if (addWhitespaceMarker) {
PPToken forceWhitespacingToken;
......
......@@ -300,10 +300,6 @@ protected:
}
static QString simplified(QByteArray buf);
private /* not corrected yet */:
void param_expanding_as_multiple_params();
void macro_argument_expansion();
private slots:
void defined();
void defined_data();
......@@ -447,49 +443,21 @@ void tst_Preprocessor::macro_args_count()
void tst_Preprocessor::invalid_param_count()
{
Client *client = 0; // no client.
Environment env;
Preprocessor preprocess(client, &env);
// The following is illegal, but shouldn't crash the preprocessor.
// 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;
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);
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;}"));
// Output is not that relevant but check that nothing triggered expansion.
QCOMPARE(client.macroArgsCount(), QList<int>());
}
void tst_Preprocessor::macro_uses()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment