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,
|
const char *MacroExpander::expand(const char *__first, const char *__last,
|
||||||
QByteArray *__result)
|
QByteArray *__result)
|
||||||
{
|
{
|
||||||
const char *start = __first;
|
|
||||||
__first = skip_blanks (__first, __last);
|
__first = skip_blanks (__first, __last);
|
||||||
lines = skip_blanks.lines;
|
lines = skip_blanks.lines;
|
||||||
|
|
||||||
@@ -362,20 +361,18 @@ const char *MacroExpander::expand(const char *__first, const char *__last,
|
|||||||
}
|
}
|
||||||
|
|
||||||
QVector<QByteArray> actuals;
|
QVector<QByteArray> actuals;
|
||||||
QVector<MacroArgumentReference> actuals_ref;
|
actuals.reserve(macro->formals().size());
|
||||||
actuals.reserve (5);
|
|
||||||
++arg_it; // skip '('
|
++arg_it; // skip '('
|
||||||
|
|
||||||
MacroExpander expand_actual (env, frame);
|
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 == ','))
|
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;
|
QByteArray expanded;
|
||||||
expand_actual (actual.constBegin (), actual.constEnd (), &expanded);
|
expand_actual(actual.constBegin (), actual.constEnd (), &expanded);
|
||||||
actuals.push_back (expanded);
|
pushActuals(actuals, macro, expanded);
|
||||||
arg_it = arg_end;
|
arg_it = arg_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,12 +380,11 @@ const char *MacroExpander::expand(const char *__first, const char *__last,
|
|||||||
{
|
{
|
||||||
++arg_it; // skip ','
|
++arg_it; // skip ','
|
||||||
|
|
||||||
arg_end = skip_argument_variadics (actuals, macro, arg_it, __last);
|
arg_end = skip_argument(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);
|
||||||
const QByteArray actual (arg_it, arg_end - arg_it);
|
|
||||||
QByteArray expanded;
|
QByteArray expanded;
|
||||||
expand_actual (actual.constBegin (), actual.constEnd (), &expanded);
|
expand_actual(actual.constBegin (), actual.constEnd (), &expanded);
|
||||||
actuals.push_back (expanded);
|
pushActuals(actuals, macro, expanded);
|
||||||
arg_it = arg_end;
|
arg_it = arg_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -425,3 +421,29 @@ const char *MacroExpander::skip_argument_variadics (QVector<QByteArray> const &_
|
|||||||
|
|
||||||
return arg_end;
|
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,
|
const char *skip_argument_variadics(const QVector<QByteArray> &actuals,
|
||||||
Macro *macro,
|
Macro *macro,
|
||||||
const char *first, const char *last);
|
const char *first, const char *last);
|
||||||
|
void pushActuals(QVector<QByteArray> & actuals, Macro *__macro, const QByteArray& expanded);
|
||||||
|
|
||||||
public: // attributes
|
public: // attributes
|
||||||
int lines;
|
int lines;
|
||||||
|
@@ -44,6 +44,7 @@ private Q_SLOTS:
|
|||||||
void va_args();
|
void va_args();
|
||||||
void named_va_args();
|
void named_va_args();
|
||||||
void first_empty_macro_arg();
|
void first_empty_macro_arg();
|
||||||
|
void param_expanding_as_multiple_params();
|
||||||
void unfinished_function_like_macro_call();
|
void unfinished_function_like_macro_call();
|
||||||
void nasty_macro_expansion();
|
void nasty_macro_expansion();
|
||||||
void tstst();
|
void tstst();
|
||||||
@@ -100,6 +101,19 @@ void tst_Preprocessor::first_empty_macro_arg()
|
|||||||
QVERIFY(preprocessed.contains("int Val2;"));
|
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()
|
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