diff --git a/src/libs/cplusplus/pp-macro-expander.cpp b/src/libs/cplusplus/pp-macro-expander.cpp index 3aa53c7d7e4..cde82884c03 100644 --- a/src/libs/cplusplus/pp-macro-expander.cpp +++ b/src/libs/cplusplus/pp-macro-expander.cpp @@ -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 actuals; - QVector 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 const &_ return arg_end; } + +void MacroExpander::pushActuals(QVector & 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; + } + } +} diff --git a/src/libs/cplusplus/pp-macro-expander.h b/src/libs/cplusplus/pp-macro-expander.h index 3352f7a4fce..97080a9f203 100644 --- a/src/libs/cplusplus/pp-macro-expander.h +++ b/src/libs/cplusplus/pp-macro-expander.h @@ -98,6 +98,7 @@ public: const char *skip_argument_variadics(const QVector &actuals, Macro *macro, const char *first, const char *last); + void pushActuals(QVector & actuals, Macro *__macro, const QByteArray& expanded); public: // attributes int lines; diff --git a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp index 06e910be639..43c9ca2d56b 100644 --- a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp +++ b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp @@ -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(""), + 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.