diff --git a/externals/simplecpp/simplecpp.cpp b/externals/simplecpp/simplecpp.cpp index 5ba6ef14f..e79dbbc5d 100644 --- a/externals/simplecpp/simplecpp.cpp +++ b/externals/simplecpp/simplecpp.cpp @@ -48,6 +48,9 @@ const simplecpp::TokenString ELSE("else"); const simplecpp::TokenString ELIF("elif"); const simplecpp::TokenString ENDIF("endif"); +const simplecpp::TokenString PRAGMA("pragma"); +const simplecpp::TokenString ONCE("once"); + template std::string toString(T t) { std::ostringstream ostr; ostr << t; @@ -1279,6 +1282,8 @@ simplecpp::TokenList simplecpp::preprocess(const simplecpp::TokenList &rawtokens std::list includes; std::stack includetokenstack; + std::set pragmaOnce; + TokenList output(files); for (const Token *rawtok = rawtokens.cbegin(); rawtok || !includetokenstack.empty();) { if (rawtok == nullptr) { @@ -1322,18 +1327,21 @@ simplecpp::TokenList simplecpp::preprocess(const simplecpp::TokenList &rawtokens } } catch (const std::runtime_error &) { } - } else if (rawtok->str == INCLUDE) { - if (ifstates.top() == TRUE) { - const std::string header(rawtok->next->str.substr(1U, rawtok->next->str.size() - 2U)); - const std::string header2 = getFileName(filedata, rawtok->location.file(), header, dui); - if (!header2.empty()) { - includetokenstack.push(gotoNextLine(rawtok)); - const TokenList *includetokens = filedata.find(header2)->second; - rawtok = includetokens ? includetokens->cbegin() : 0; - continue; - } else { - // TODO: Write warning message - } + } else if (ifstates.top() == TRUE && rawtok->str == INCLUDE) { + const std::string header(rawtok->next->str.substr(1U, rawtok->next->str.size() - 2U)); + const std::string header2 = getFileName(filedata, rawtok->location.file(), header, dui); + if (!header2.empty() && pragmaOnce.find(header2) == pragmaOnce.end()) { + includetokenstack.push(gotoNextLine(rawtok)); + const TokenList *includetokens = filedata.find(header2)->second; + rawtok = includetokens ? includetokens->cbegin() : 0; + continue; + } else { + simplecpp::Output output(files); + output.type = Output::Type::MISSING_INCLUDE; + output.location = rawtok->location; + output.msg = "Header not found: " + rawtok->next->str; + if (outputList) + outputList->push_back(output); } } else if (rawtok->str == IF || rawtok->str == IFDEF || rawtok->str == IFNDEF || rawtok->str == ELIF) { bool conditionIsTrue; @@ -1425,6 +1433,8 @@ simplecpp::TokenList simplecpp::preprocess(const simplecpp::TokenList &rawtokens if (sameline(rawtok, tok)) macros.erase(tok->str); } + } else if (ifstates.top() == TRUE && rawtok->str == PRAGMA && rawtok->next && rawtok->next->str == ONCE && sameline(rawtok,rawtok->next)) { + pragmaOnce.insert(rawtok->location.file()); } rawtok = gotoNextLine(rawtok); continue; diff --git a/externals/simplecpp/simplecpp.h b/externals/simplecpp/simplecpp.h index 32165a978..90bd45df8 100644 --- a/externals/simplecpp/simplecpp.h +++ b/externals/simplecpp/simplecpp.h @@ -123,8 +123,9 @@ private: struct Output { Output(const std::vector &files) : type(ERROR), location(files) {} enum Type { - ERROR, /* error */ - WARNING /* warning */ + ERROR, /* #error */ + WARNING, /* #warning */ + MISSING_INCLUDE } type; Location location; std::string msg; diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 08d443da7..6674ed3cf 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -121,6 +121,9 @@ unsigned int CppCheck::processFile(const std::string& filename, std::istream& fi } if (_settings.checkConfiguration) { + for (std::set::const_iterator it = configurations.begin(); it != configurations.end(); ++it) + (void)preprocessor.getcode(tokens1, *it, files, true); + return 0; } diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 946087b08..c04d95f2e 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -512,11 +512,21 @@ std::string Preprocessor::getcode(const simplecpp::TokenList &tokens1, const std bool showerror = (!_settings.userDefines.empty() && !_settings.force); for (simplecpp::OutputList::const_iterator it = outputList.begin(); it != outputList.end(); ++it) { - if (it->type == simplecpp::Output::ERROR) { + switch (it->type) { + case simplecpp::Output::ERROR: if (it->msg.compare(0,6,"#error")!=0 || showerror) error(it->location.file(), it->location.line, it->msg); return ""; + case simplecpp::Output::WARNING: + break; + case simplecpp::Output::MISSING_INCLUDE: { + const std::string::size_type pos1 = it->msg.find_first_of("<\""); + const std::string::size_type pos2 = it->msg.find_first_of(">\"", pos1 + 1U); + if (pos1 < pos2 && pos2 != std::string::npos) + missingInclude(it->location.file(), it->location.line, it->msg.substr(pos1+1, pos2-pos1-1), it->msg[pos1] == '\"' ? UserHeader : SystemHeader); } + break; + }; } // directive list.. @@ -649,10 +659,20 @@ std::string Preprocessor::getcode(const std::string &filedata, const std::string inlineSuppressions(tokens1); for (simplecpp::OutputList::const_iterator it = outputList.begin(); it != outputList.end(); ++it) { - if (it->type == simplecpp::Output::ERROR) { + switch (it->type) { + case simplecpp::Output::ERROR: error(it->location.file(), it->location.line, it->msg); return ""; + case simplecpp::Output::WARNING: + break; + case simplecpp::Output::MISSING_INCLUDE: { + const std::string::size_type pos1 = it->msg.find_first_of("<\""); + const std::string::size_type pos2 = it->msg.find_first_of(">\"", pos1 + 1U); + if (pos1 < pos2 && pos2 != std::string::npos) + missingInclude(it->location.file(), it->location.line, it->msg.substr(pos1+1, pos2-pos1-1), it->msg[pos1] == '\"' ? UserHeader : SystemHeader); } + break; + }; } return getcode(tokens1, cfg, files, filedata.find("#file") != std::string::npos);