Commit ffd58c57 authored by Francois Ferrand's avatar Francois Ferrand Committed by Erik Verbruggen

Preprocessor: Handle variadic arguments (__VA_ARGS__).

Change-Id: I69aa6c5e01ea97a4413f77f20ebbb4d4beb971aa
Reviewed-by: default avatarErik Verbruggen <erik.verbruggen@nokia.com>
parent f0b122e3
......@@ -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("...");
......
......@@ -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
}
......
......@@ -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("<stdin>"),
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("<stdin>"),
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.
......
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