diff options
-rw-r--r-- | src/libs/cplusplus/pp-engine.cpp | 27 | ||||
-rw-r--r-- | tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp | 58 |
2 files changed, 32 insertions, 53 deletions
diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index 718f3dd0df..fa780f77fe 100644 --- a/src/libs/cplusplus/pp-engine.cpp +++ b/src/libs/cplusplus/pp-engine.cpp @@ -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; diff --git a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp index e703cf2f34..b5cb82649d 100644 --- a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp +++ b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp @@ -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() |