From e9fef003ac80a6305dd7954a91a11fb6daf72c23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sun, 24 Jul 2016 14:02:21 +0200 Subject: [PATCH] Preprocessor: refactoring directives, they are now only set once for each file --- lib/cppcheck.cpp | 3 ++ lib/preprocessor.cpp | 59 ++++++++++++++++++++++++--------------- lib/preprocessor.h | 3 ++ test/testpreprocessor.cpp | 1 + 4 files changed, 44 insertions(+), 22 deletions(-) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 6674ed3cf..dc4488a0c 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -112,6 +112,9 @@ unsigned int CppCheck::processFile(const std::string& filename, std::istream& fi tokens1.removeComments(); preprocessor.removeComments(); + // Get directives + preprocessor.setDirectives(tokens1); + // Get configurations.. if (_settings.userDefines.empty() || _settings.force) { Timer t("Preprocessor::getConfigs", _settings.showtime, &S_timerResults); diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index c6ae24820..e4a0a498e 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -135,6 +135,39 @@ void Preprocessor::inlineSuppressions(const simplecpp::TokenList &tokens) } } +void Preprocessor::setDirectives(const simplecpp::TokenList &tokens1) +{ + // directive list.. + directives.clear(); + + std::list list; + list.push_back(&tokens1); + for (std::map::const_iterator it = tokenlists.begin(); it != tokenlists.end(); ++it) { + list.push_back(it->second); + } + + for (std::list::const_iterator it = list.begin(); it != list.end(); ++it) { + for (const simplecpp::Token *tok = (*it)->cbegin(); tok; tok = tok ? tok->next : nullptr) { + if ((tok->op != '#') || (tok->previous && tok->previous->location.line == tok->location.line)) + continue; + if (tok->next && tok->next->str == "endfile") + continue; + Directive directive(tok->location.file(), tok->location.line, ""); + for (const simplecpp::Token *tok2 = tok; tok2 && tok2->location.line == directive.linenr; tok2 = tok2->next) { + if (tok2->comment) + continue; + if (!directive.str.empty() && (tok2->location.col > tok2->previous->location.col + tok2->previous->str.size())) + directive.str += ' '; + if (directive.str == "#" && tok2->str == "file") + directive.str += "include"; + else + directive.str += tok2->str; + } + directives.push_back(directive); + } + } +} + static bool sameline(const simplecpp::Token *tok1, const simplecpp::Token *tok2) { return tok1 && tok2 && tok1->location.sameline(tok2->location); @@ -465,27 +498,6 @@ std::string Preprocessor::getcode(const simplecpp::TokenList &tokens1, const std }; } - // directive list.. - directives.clear(); - for (const simplecpp::Token *tok = tokens1.cbegin(); tok; tok = tok ? tok->next : nullptr) { - if ((tok->op != '#') || (tok->previous && tok->previous->location.line == tok->location.line)) - continue; - if (tok->next && tok->next->str == "endfile") - continue; - Directive directive(tok->location.file(), tok->location.line, ""); - for (const simplecpp::Token *tok2 = tok; tok2 && tok2->location.line == directive.linenr; tok2 = tok2->next) { - if (tok2->comment) - continue; - if (!directive.str.empty() && (tok2->location.col > tok2->previous->location.col + tok2->previous->str.size())) - directive.str += ' '; - if (directive.str == "#" && tok2->str == "file") - directive.str += "include"; - else - directive.str += tok2->str; - } - directives.push_back(directive); - } - // ensure that guessed define macros without value are not used in the code for (std::list::const_iterator defineIt = dui.defines.begin(); defineIt != dui.defines.end(); ++defineIt) { if (defineIt->find("=") != std::string::npos) @@ -591,8 +603,11 @@ std::string Preprocessor::getcode(const std::string &filedata, const std::string std::vector files; std::istringstream istr(filedata); - const simplecpp::TokenList &tokens1 = simplecpp::TokenList(istr, files, Path::simplifyPath(filename), &outputList); + simplecpp::TokenList tokens1(istr, files, Path::simplifyPath(filename), &outputList); inlineSuppressions(tokens1); + tokens1.removeComments(); + removeComments(); + setDirectives(tokens1); for (simplecpp::OutputList::const_iterator it = outputList.begin(); it != outputList.end(); ++it) { switch (it->type) { diff --git a/lib/preprocessor.h b/lib/preprocessor.h index a4784cf0c..e5d6a8d87 100644 --- a/lib/preprocessor.h +++ b/lib/preprocessor.h @@ -88,12 +88,15 @@ public: void inlineSuppressions(const simplecpp::TokenList &tokens); + void setDirectives(const simplecpp::TokenList &tokens); + std::set getConfigs(const simplecpp::TokenList &tokens) const; void loadFiles(const simplecpp::TokenList &rawtokens, std::vector &files); void removeComments(); + /** * Extract the code for each configuration * @param istr The (file/string) stream to read from. diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index b758bb6af..8ee8a0368 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -264,6 +264,7 @@ private: simplecpp::TokenList tokens(istr, files, filename, &outputList); tokens.removeComments(); const std::set configs(preprocessor0.getConfigs(tokens)); + preprocessor0.setDirectives(tokens); for (std::set::const_iterator it = configs.begin(); it != configs.end(); ++it) { try { const std::string &cfgcode = preprocessor0.getcode(tokens, *it, files, std::string(code).find("#file") != std::string::npos);