diff --git a/src/libs/cplusplus/Macro.cpp b/src/libs/cplusplus/Macro.cpp index 802f126e2a5ab90f0c8e8c0505fb77fc21bbb3ef..7020f5f01c0ba5630848c4d7a496b013abae08d7 100644 --- a/src/libs/cplusplus/Macro.cpp +++ b/src/libs/cplusplus/Macro.cpp @@ -78,7 +78,8 @@ QString Macro::decoratedName() const text += QLatin1String(", "); else first = false; - text += QString::fromUtf8(formal.constData(), formal.size()); + if (formal != "__VA_ARGS__") + text += QString::fromUtf8(formal.constData(), formal.size()); } if (f._variadic) text += QLatin1String("..."); diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index af27609f8466a0949319977c36ad863fa1db7f3e..dbdd5e0b6b8993f745a349841c25eb541ebd048d 100644 --- a/src/libs/cplusplus/pp-engine.cpp +++ b/src/libs/cplusplus/pp-engine.cpp @@ -1178,18 +1178,22 @@ void Preprocessor::processDefine(TokenIterator firstToken, TokenIterator lastTok macro.setLength(endOfToken(lastToken[- 1]) - startOfToken(*firstToken)); ++tk; // skip T_IDENTIFIER + bool hasIdentifier = false; if (tk->is(T_LPAREN) && ! tk->f.whitespace) { // a function-like macro definition macro.setFunctionLike(true); ++tk; // skip T_LPAREN if (tk->is(T_IDENTIFIER)) { + hasIdentifier = true; macro.addFormal(tokenText(*tk)); ++tk; // skip T_IDENTIFIER while (tk->is(T_COMMA)) { ++tk;// skip T_COMMA - if (tk->isNot(T_IDENTIFIER)) + if (tk->isNot(T_IDENTIFIER)) { + hasIdentifier = false; break; + } macro.addFormal(tokenText(*tk)); ++tk; // skip T_IDENTIFIER } @@ -1197,6 +1201,8 @@ void Preprocessor::processDefine(TokenIterator firstToken, TokenIterator lastTok if (tk->is(T_DOT_DOT_DOT)) { macro.setVariadic(true); + if (!hasIdentifier) + macro.addFormal("__VA_ARGS__"); ++tk; // skip T_DOT_DOT_DOT } diff --git a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp index 6d08d46f5a16b12dc16ff21e32869ca8cf0ec249..1c5d6fd320f01f85207d3d9084f21ae6600f99cd 100644 --- a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp +++ b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp @@ -41,11 +41,47 @@ class tst_Preprocessor: public QObject Q_OBJECT private Q_SLOTS: + void va_args(); + void named_va_args(); void unfinished_function_like_macro_call(); void nasty_macro_expansion(); void tstst(); }; +void tst_Preprocessor::va_args() +{ + Client *client = 0; // no client. + Environment env; + + Preprocessor preprocess(client, &env); + QByteArray preprocessed = preprocess(QLatin1String(""), + QByteArray("\n#define foo(...) int f(__VA_ARGS__);" + "\nfoo( )\n" + "\nfoo(int a)\n" + "\nfoo(int a,int b)\n")); + + QVERIFY(preprocessed.contains("int f();")); + QVERIFY(preprocessed.contains("int f(int a);")); + QVERIFY(preprocessed.contains("int f(int a,int b);")); +} + +void tst_Preprocessor::named_va_args() +{ + Client *client = 0; // no client. + Environment env; + + Preprocessor preprocess(client, &env); + QByteArray preprocessed = preprocess(QLatin1String(""), + QByteArray("\n#define foo(ARGS...) int f(ARGS);" + "\nfoo( )\n" + "\nfoo(int a)\n" + "\nfoo(int a,int b)\n")); + + QVERIFY(preprocessed.contains("int f();")); + QVERIFY(preprocessed.contains("int f(int a);")); + QVERIFY(preprocessed.contains("int f(int a,int b);")); +} + void tst_Preprocessor::unfinished_function_like_macro_call() { Client *client = 0; // no client.