diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index d5733e543..ead0439ef 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -65,7 +65,7 @@ static void AddFilesToList(const std::string& FileList, std::vector } } -static void AddInclPathsToList(const std::string& FileList, std::list& PathNames) +static void AddInclPathsToList(const std::string& FileList, std::list* PathNames) { // to keep things initially simple, if the file can't be opened, just be // silent and move on @@ -81,12 +81,19 @@ static void AddInclPathsToList(const std::string& FileList, std::listpush_back(PathName); } } } } +static void AddPathsToSet(const std::string& FileName, std::set* set) +{ + std::list templist; + AddInclPathsToList(FileName, &templist); + set->insert(templist.begin(), templist.end()); +} + CmdLineParser::CmdLineParser(Settings *settings) : _settings(settings) , _showHelp(false) @@ -435,7 +442,14 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[]) _settings->userIncludes.push_back(path); } else if (std::strncmp(argv[i], "--includes-file=", 16) == 0) { // open this file and read every input file (1 file name per line) - AddInclPathsToList(16 + argv[i], _settings->_includePaths); + AddInclPathsToList(16 + argv[i], &_settings->_includePaths); + } else if (std::strncmp(argv[i], "--config-exclude=",17) ==0) { + std::string path = argv[i] + 17; + path = Path::fromNativeSeparators(path); + _settings->configExcludePaths.insert(path); + } else if (std::strncmp(argv[i], "--config-excludes-file=", 23) == 0) { + // open this file and read every input file (1 file name per line) + AddPathsToSet(23 + argv[i], &_settings->configExcludePaths); } // file list specified @@ -825,6 +839,13 @@ void CmdLineParser::PrintHelp() " First given path is searched for contained header\n" " files first. If paths are relative to source files,\n" " this is not needed.\n" + " --config-exclude=\n" + " Path (prefix) to be excluded from configuration checking.\n" + " Preprocessor configurations defined in headers (but not sources)\n" + " matching the prefix will not be considered for evaluation\n" + " of configuration alternatives\n" + " --config-excludes-file=\n" + " A file that contains a list of config-excludes\n" " --include=\n" " Force inclusion of a file before the checked file. Can\n" " be used for example when checking the Linux kernel,\n" diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 2aac37c39..7edb84062 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -1204,13 +1204,14 @@ std::list Preprocessor::getcfgs(const std::string &filedata, const // constants defined through "#define" in the code.. std::set defines; std::map alldefinesmap(defs); + std::stack > includeStack; + includeStack.push(std::pair(filename,false)); // How deep into included files are we currently parsing? // 0=>Source file, 1=>Included by source file, 2=>included by header that was included by source file, etc int filelevel = 0; bool includeguard = false; - unsigned int linenr = 0; std::istringstream istr(filedata); std::string line; @@ -1228,12 +1229,23 @@ std::list Preprocessor::getcfgs(const std::string &filedata, const if (line.compare(0, 6, "#file ") == 0) { includeguard = true; + std::string::size_type start=line.find("\""); + std::string::size_type end=line.find("\"",start+1); + std::string includeFile=line.substr(start+1,end-start-1); + bool fileExcluded = false; ++filelevel; + if (! _settings) { + fileExcluded = false; + } else { + fileExcluded = _settings->configurationExcluded(includeFile); + } + includeStack.push(std::pair(includeFile,fileExcluded)); continue; } else if (line == "#endfile") { includeguard = false; + includeStack.pop(); if (filelevel > 0) --filelevel; continue; @@ -1404,7 +1416,16 @@ std::list Preprocessor::getcfgs(const std::string &filedata, const } if (std::find(ret.begin(), ret.end(), def) == ret.end()) { - ret.push_back(def); + if (!includeStack.top().second) { + ret.push_back(def); + } else { + if (_errorLogger && _settings && _settings->debugwarnings) { + std::list locationList; + const ErrorLogger::ErrorMessage errmsg(locationList, Severity::debug, + "Configuration not considered: " + def +" for file:"+includeStack.top().first, "debug", false); + _errorLogger->reportErr(errmsg); + } + } } } diff --git a/lib/settings.h b/lib/settings.h index 6743533cb..87e4a0ab4 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -175,6 +175,10 @@ public: /** @brief forced includes given by the user */ std::list userIncludes; + /** @brief include paths excluded from checking the configuration */ + std::set configExcludePaths; + + /** @brief --report-progress */ bool reportProgress; @@ -251,6 +255,20 @@ public: platformType == Win32W || platformType == Win64; } + + /** + * @brief return true if a file is to be excluded from configuration checking + * @return true for the file to be excluded. + */ + bool configurationExcluded(const std::string &file) const { + for (std::set::const_iterator i=configExcludePaths.begin(); i!=configExcludePaths.end(); ++i) { + if (file.length()>=i->length() && file.compare(0,i->length(),*i)==0) { + return true; + } + } + return false; + } + }; /// @}