forked from qt-creator/qt-creator
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: Erik Verbruggen <erik.verbruggen@nokia.com>
This commit is contained in:
committed by
Erik Verbruggen
parent
3e9105e401
commit
558b6e08ae
@@ -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.
|
||||
|
Reference in New Issue
Block a user