diff --git a/.travis.yml b/.travis.yml index f071e49c0..620543516 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,10 +37,6 @@ script: - touch lib/mathlib.cpp test/testmathlib.cpp - make test -j4 CPPFLAGS=-DTEST_MATHLIB_VALUE - touch lib/mathlib.cpp test/testmathlib.cpp -# slow test in testtokenizer that is only executed on travis - - touch test/testtokenizer.cpp - - make testrunner -j4 CPPFLAGS=-DTRAVIS && ./testrunner TestTokenizer - - touch test/testtokenizer.cpp # compile cppcheck, default build - make test -j4 # compile gui diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index dc87855d6..d9082e4d8 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -2627,7 +2627,7 @@ private: std::string innercode; std::map innermacros = macros; innermacros.erase(innerMacroName); - innerMacro->code(innerparams, innerparams, innermacros, innercode); + innerMacro->code(innerparams, innermacros, innercode); params2[ipar] = innercode; } } @@ -2708,13 +2708,12 @@ public: /** * get expanded code for this macro - * @param params2 completely expanded macro parameters - * @param params3 non-expanded macro parameters + * @param params2 macro parameters * @param macros macro definitions (recursion) * @param macrocode output string * @return true if the expanding was successful */ - bool code(const std::vector ¶ms2, const std::vector ¶ms3, const std::map ¯os, std::string ¯ocode) const { + bool code(const std::vector ¶ms2, const std::map ¯os, std::string ¯ocode) const { if (_nopar || (_params.empty() && _variadic)) { macrocode = _macro.substr(1 + _macro.find(')')); if (macrocode.empty()) @@ -2773,15 +2772,12 @@ public: while (tok && tok->str() != ")") tok = tok->next(); if (tok) { - bool noprescan = false; bool optcomma = false; while (nullptr != (tok = tok->next())) { std::string str = tok->str(); if (str[0] == '#' || tok->isName()) { - if (str == "##") { - noprescan = true; + if (str == "##") continue; - } const bool stringify(str[0] == '#'); if (stringify) { @@ -2803,14 +2799,8 @@ public: // Macro had more parameters than caller used. macrocode = ""; return false; - } else { - if (noprescan) { - noprescan = false; - str = params3[i]; - } else { - str = givenparams[i]; - } - } + } else + str = givenparams[i]; break; } @@ -3094,13 +3084,13 @@ std::string Preprocessor::expandMacros(const std::string &code, std::string file // the macro again, the macro should not be expanded again. // The limits are used to prevent recursive expanding. // * When a macro is expanded its limit position is set to - // the first expanded character. + // the last expanded character. // * macros are only allowed to be expanded when the - // the position is before the limit. - // * The limit is relative to the start of the "line" - // variable. Inserting and deleting text after the limit + // the position is beyond the limit. + // * The limit is relative to the end of the "line" + // variable. Inserting and deleting text before the limit // without updating the limit is safe. - // * when base_pos is prior to a limit the limit needs to be + // * when pos goes beyond a limit the limit needs to be // deleted because it is unsafe to insert/delete text // after the limit otherwise std::map limits; @@ -3108,54 +3098,9 @@ std::string Preprocessor::expandMacros(const std::string &code, std::string file // pos is the current position in line std::string::size_type pos = 0; - // base_pos is the starting point of the current macro expansion - // macro expansion only commences once all macros have been scanned - // recursively and have been pushed on the macro expansion stack - std::string::size_type base_pos; - - // Offset from the end of the line from where further macro - // expansion is not necessary - std::string::size_type end_pos = 0; - // scan line to see if there are any macros to expand.. unsigned int tmpLinenr = 0; - - // The stack of starting positions of macros to be expanded along - // with their unexpanded parameters - std::stack>> pos_stack; - - // Flag that indicates whether we are scanning line or processing the macro stack - bool processing_stack = false; - - std::vector unexpanded_params; - - while ((pos < (line.size() - end_pos)) || !(pos_stack.empty())) { - if (pos >= line.size() - end_pos) { - // We are at the end of the line so start processing the stack - pos = pos_stack.top().first; - unexpanded_params = pos_stack.top().second; - pos_stack.pop(); - if (processing_stack) { - // Remove old limits - for (std::map::iterator iter = limits.begin(); - iter != limits.end();) { - if (base_pos <= iter->second) { - // We have gone past this limit range, so just delete it - limits.erase(iter++); - } else { - ++iter; - } - } - } - base_pos = pos; - if (pos >= (line.size() - end_pos)) { - // The macro expansion popped off the stack exceeds the - // end position for macro expansion so discard it - continue; - } - processing_stack = true; - } - + while (pos < line.size()) { if (line[pos] == '\n') ++tmpLinenr; @@ -3188,7 +3133,7 @@ std::string Preprocessor::expandMacros(const std::string &code, std::string file // found an identifier.. // the "while" is used in case the expanded macro will immediately call another macro - while ((pos < (line.size() - end_pos)) && (std::isalpha((unsigned char)line[pos]) || line[pos] == '_')) { + while (pos < line.length() && (std::isalpha((unsigned char)line[pos]) || line[pos] == '_')) { // pos1 = start position of macro const std::string::size_type pos1 = pos++; @@ -3211,22 +3156,14 @@ std::string Preprocessor::expandMacros(const std::string &code, std::string file // macro { const std::map::const_iterator it2 = limits.find(macro); - if (it2 != limits.end() && pos1 > it2->second) { - // Update end_pos to avoid trying to expand this - // macro again - end_pos = line.size() - pos1; + if (it2 != limits.end() && pos <= line.length() - it2->second) break; - } } - std::vector params; - // get parameters from line.. - if (macro->params().size() && pos >= line.length()) { - pos_stack.push(std::make_pair(pos1, params)); + if (macro->params().size() && pos >= line.length()) break; - } - + std::vector params; std::string::size_type pos2 = pos; // number of newlines within macro use @@ -3239,23 +3176,9 @@ std::string Preprocessor::expandMacros(const std::string &code, std::string file getparams(line,pos2,params,numberOfNewlines,endFound); - // something went wrong (eg. perhaps the parameters - // require a prescan?) so bail out but push the - // expansion onto the stack assuming we'll be able to - // get the parameters after a prescan - if (!endFound && params.size() != 0) { - pos_stack.push(std::make_pair(pos1, params)); - processing_stack = false; + // something went wrong so bail out + if (!endFound) break; - } - } - pos_stack.push(std::make_pair(pos1, params)); - if (processing_stack) { - // Expand macro parameters - processing_stack = false; - } else { - // Continue scanning - continue; } // Just an empty parameter => clear @@ -3263,14 +3186,12 @@ std::string Preprocessor::expandMacros(const std::string &code, std::string file params.clear(); // Check that it's the same number of parameters.. - if (!macro->variadic() && params.size() != macro->params().size()) { - pos_stack.pop(); + if (!macro->variadic() && params.size() != macro->params().size()) break; - } // Create macro code.. std::string tempMacro; - if (!macro->code(params, unexpanded_params, macros, tempMacro)) { + if (!macro->code(params, macros, tempMacro)) { // Syntax error in code writeError(filename, linenr + tmpLinenr, @@ -3292,8 +3213,19 @@ std::string Preprocessor::expandMacros(const std::string &code, std::string file if (macro->variadic() || macro->nopar() || !macro->params().empty()) ++pos2; - // don't allow this macro to be expanded again after pos1 - limits[macro] = pos1; + // Remove old limits + for (std::map::iterator iter = limits.begin(); + iter != limits.end();) { + if ((line.length() - pos1) < iter->second) { + // We have gone past this limit, so just delete it + limits.erase(iter++); + } else { + ++iter; + } + } + + // don't allow this macro to be expanded again before pos2 + limits[macro] = line.length() - pos2; // erase macro line.erase(pos1, pos2 - pos1); diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index 9f8e4c0e5..9a74bde1d 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -187,7 +187,6 @@ private: TEST_CASE(macro_incdec); // separate ++ and -- with space when expanding such macro: '#define M(X) A-X' TEST_CASE(macro_switchCase); TEST_CASE(macro_NULL); // skip #define NULL .. it is replaced in the tokenizer - TEST_CASE(macro_prescan); // #7563: Macro parameter prescan TEST_CASE(string1); TEST_CASE(string2); TEST_CASE(string3); @@ -1993,25 +1992,6 @@ private: ASSERT_EQUALS("\nNULL", OurPreprocessor::expandMacros("#define NULL 0\nNULL")); } - void macro_prescan() const { - const char filedata[] = "#define CONCAT_(a, b) a##b\n" - "#define CONCAT(a, b) CONCAT_(a, b)\n" - "#define VALUE(value) CONCAT(CONCAT(text1, value), text3),\n" - "enum {\n" - "VALUE(1)\n" - "VALUE(2)\n" - "VALUE(3)\n" - "NUM_VALUES,\n" - "};\n"; - ASSERT_EQUALS("\n\n\nenum {\n" - "$$$text11text3,\n" - "$$$text12text3,\n" - "$$$text13text3,\n" - "NUM_VALUES,\n" - "};\n", - OurPreprocessor::expandMacros(filedata)); - } - void string1() { const char filedata[] = "int main()" "{" diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index c44d38ca8..997065a6c 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -8342,9 +8342,6 @@ private: } void compileLimits() { -#ifdef TRAVIS - // FIXME: this test is very slow when old preprocessor is used. therefore it is only run on travis. - const char raw_code[] = "#define PTR1 (* (* (* (* (* (* (* (* (* (*\n" "#define PTR2 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1\n" "#define PTR3 PTR2 PTR2 PTR2 PTR2 PTR2 PTR2 PTR2 PTR2 PTR2 PTR2\n" @@ -8370,7 +8367,6 @@ private: const std::string code = preprocessor.getcode(filedata, emptyString, emptyString); tokenizeAndStringify(code.c_str()); // just survive... -#endif } bool isStartOfExecutableScope(int offset, const char code[]) {