forked from qt-creator/qt-creator
Preprocessor: Handle variadic arguments (__VA_ARGS__).
Change-Id: I69aa6c5e01ea97a4413f77f20ebbb4d4beb971aa Reviewed-by: Erik Verbruggen <erik.verbruggen@nokia.com>
This commit is contained in:
committed by
Erik Verbruggen
parent
f0b122e3d2
commit
ffd58c577a
@@ -78,7 +78,8 @@ QString Macro::decoratedName() const
|
|||||||
text += QLatin1String(", ");
|
text += QLatin1String(", ");
|
||||||
else
|
else
|
||||||
first = false;
|
first = false;
|
||||||
text += QString::fromUtf8(formal.constData(), formal.size());
|
if (formal != "__VA_ARGS__")
|
||||||
|
text += QString::fromUtf8(formal.constData(), formal.size());
|
||||||
}
|
}
|
||||||
if (f._variadic)
|
if (f._variadic)
|
||||||
text += QLatin1String("...");
|
text += QLatin1String("...");
|
||||||
|
@@ -1178,18 +1178,22 @@ void Preprocessor::processDefine(TokenIterator firstToken, TokenIterator lastTok
|
|||||||
macro.setLength(endOfToken(lastToken[- 1]) - startOfToken(*firstToken));
|
macro.setLength(endOfToken(lastToken[- 1]) - startOfToken(*firstToken));
|
||||||
++tk; // skip T_IDENTIFIER
|
++tk; // skip T_IDENTIFIER
|
||||||
|
|
||||||
|
bool hasIdentifier = false;
|
||||||
if (tk->is(T_LPAREN) && ! tk->f.whitespace) {
|
if (tk->is(T_LPAREN) && ! tk->f.whitespace) {
|
||||||
// a function-like macro definition
|
// a function-like macro definition
|
||||||
macro.setFunctionLike(true);
|
macro.setFunctionLike(true);
|
||||||
|
|
||||||
++tk; // skip T_LPAREN
|
++tk; // skip T_LPAREN
|
||||||
if (tk->is(T_IDENTIFIER)) {
|
if (tk->is(T_IDENTIFIER)) {
|
||||||
|
hasIdentifier = true;
|
||||||
macro.addFormal(tokenText(*tk));
|
macro.addFormal(tokenText(*tk));
|
||||||
++tk; // skip T_IDENTIFIER
|
++tk; // skip T_IDENTIFIER
|
||||||
while (tk->is(T_COMMA)) {
|
while (tk->is(T_COMMA)) {
|
||||||
++tk;// skip T_COMMA
|
++tk;// skip T_COMMA
|
||||||
if (tk->isNot(T_IDENTIFIER))
|
if (tk->isNot(T_IDENTIFIER)) {
|
||||||
|
hasIdentifier = false;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
macro.addFormal(tokenText(*tk));
|
macro.addFormal(tokenText(*tk));
|
||||||
++tk; // skip T_IDENTIFIER
|
++tk; // skip T_IDENTIFIER
|
||||||
}
|
}
|
||||||
@@ -1197,6 +1201,8 @@ void Preprocessor::processDefine(TokenIterator firstToken, TokenIterator lastTok
|
|||||||
|
|
||||||
if (tk->is(T_DOT_DOT_DOT)) {
|
if (tk->is(T_DOT_DOT_DOT)) {
|
||||||
macro.setVariadic(true);
|
macro.setVariadic(true);
|
||||||
|
if (!hasIdentifier)
|
||||||
|
macro.addFormal("__VA_ARGS__");
|
||||||
++tk; // skip T_DOT_DOT_DOT
|
++tk; // skip T_DOT_DOT_DOT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -41,11 +41,47 @@ class tst_Preprocessor: public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
|
void va_args();
|
||||||
|
void named_va_args();
|
||||||
void unfinished_function_like_macro_call();
|
void unfinished_function_like_macro_call();
|
||||||
void nasty_macro_expansion();
|
void nasty_macro_expansion();
|
||||||
void tstst();
|
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()
|
void tst_Preprocessor::unfinished_function_like_macro_call()
|
||||||
{
|
{
|
||||||
Client *client = 0; // no client.
|
Client *client = 0; // no client.
|
||||||
|
Reference in New Issue
Block a user