Commit 558b6e08 authored by Francois Ferrand's avatar Francois Ferrand Committed by Erik Verbruggen

Preprocessor: fix expanding macro arguments.

Expanding macro arguments can add or remove argument for a nested macro,
so the actual parameters list was not correct.

Also, remove unused arguments reference list and reserve space for the
expected number of arguments.

Change-Id: I4cf369cbb3909927c6bf65750bd715fa6f070fad
Reviewed-by: default avatarErik Verbruggen <erik.verbruggen@nokia.com>
parent 3e9105e4
......@@ -103,7 +103,6 @@ const char *MacroExpander::operator()(const char *first, const char *last,
const char *MacroExpander::expand(const char *__first, const char *__last,
QByteArray *__result)
{
const char *start = __first;
__first = skip_blanks (__first, __last);
lines = skip_blanks.lines;
......@@ -362,20 +361,18 @@ const char *MacroExpander::expand(const char *__first, const char *__last,
}
QVector<QByteArray> actuals;
QVector<MacroArgumentReference> actuals_ref;
actuals.reserve (5);
actuals.reserve(macro->formals().size());
++arg_it; // skip '('
MacroExpander expand_actual (env, frame);
const char *arg_end = skip_argument_variadics (actuals, macro, arg_it, __last);
const char *arg_end = skip_argument(arg_it, __last);
if (arg_it != arg_end || (arg_end != __last && *arg_end == ','))
{
actuals_ref.append(MacroArgumentReference(start_offset + (arg_it-start), arg_end - arg_it));
const QByteArray actual (arg_it, arg_end - arg_it);
const QByteArray actual(arg_it, arg_end - arg_it);
QByteArray expanded;
expand_actual (actual.constBegin (), actual.constEnd (), &expanded);
actuals.push_back (expanded);
expand_actual(actual.constBegin (), actual.constEnd (), &expanded);
pushActuals(actuals, macro, expanded);
arg_it = arg_end;
}
......@@ -383,12 +380,11 @@ const char *MacroExpander::expand(const char *__first, const char *__last,
{
++arg_it; // skip ','
arg_end = skip_argument_variadics (actuals, macro, arg_it, __last);
actuals_ref.append(MacroArgumentReference(start_offset + (arg_it-start), arg_end - arg_it));
const QByteArray actual (arg_it, arg_end - arg_it);
arg_end = skip_argument(arg_it, __last);
const QByteArray actual(arg_it, arg_end - arg_it);
QByteArray expanded;
expand_actual (actual.constBegin (), actual.constEnd (), &expanded);
actuals.push_back (expanded);
expand_actual(actual.constBegin (), actual.constEnd (), &expanded);
pushActuals(actuals, macro, expanded);
arg_it = arg_end;
}
......@@ -425,3 +421,29 @@ const char *MacroExpander::skip_argument_variadics (QVector<QByteArray> const &_
return arg_end;
}
void MacroExpander::pushActuals(QVector<QByteArray> & actuals, Macro *__macro, const QByteArray& expanded)
{
if (__macro->isVariadic() && actuals.count() == __macro->formals().count()) {
//already enough params --> append to the last one
QByteArray& b = actuals.last();
b.append(",");
b.append(expanded.trimmed());
}
else {
const char * __first = expanded.constData();
const char * __last = __first + expanded.length();
const char * arg_it = __first;
const char *arg_end = skip_argument_variadics(actuals, __macro, arg_it, __last);
actuals.push_back(QByteArray(arg_it, arg_end - arg_it).trimmed());
arg_it = arg_end;
while (arg_it != __last) {
++arg_it; // skip ','
const char *arg_end = skip_argument_variadics(actuals, __macro, arg_it, __last);
actuals.push_back(QByteArray(arg_it, arg_end - arg_it).trimmed());
arg_it = arg_end;
}
}
}
......@@ -98,6 +98,7 @@ public:
const char *skip_argument_variadics(const QVector<QByteArray> &actuals,
Macro *macro,
const char *first, const char *last);
void pushActuals(QVector<QByteArray> & actuals, Macro *__macro, const QByteArray& expanded);
public: // attributes
int lines;
......
......@@ -44,6 +44,7 @@ private Q_SLOTS:
void va_args();
void named_va_args();
void first_empty_macro_arg();
void param_expanding_as_multiple_params();
void unfinished_function_like_macro_call();
void nasty_macro_expansion();
void tstst();
......@@ -100,6 +101,19 @@ void tst_Preprocessor::first_empty_macro_arg()
QVERIFY(preprocessed.contains("int Val2;"));
}
void tst_Preprocessor::param_expanding_as_multiple_params()
{
Client *client = 0; // no client.
Environment env;
Preprocessor preprocess(client, &env);
QByteArray preprocessed = preprocess(QLatin1String("<stdin>"),
QByteArray("\n#define foo(a,b) int f(a,b);"
"\n#define ARGS(t) t a,t b"
"\nfoo(ARGS(int))"));
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