@@ -99,9 +99,9 @@ class CppCheck::CppCheckLogger : public ErrorLogger
9999 closePlist ();
100100 }
101101
102- void setRemarkComments ( std::vector<RemarkComment> remarkComments)
102+ std::vector<RemarkComment>& remarkComments ( )
103103 {
104- mRemarkComments = std::move (remarkComments) ;
104+ return mRemarkComments ;
105105 }
106106
107107 void setLocationMacros (const Token* startTok, const std::vector<std::string>& files)
@@ -123,17 +123,25 @@ class CppCheck::CppCheckLogger : public ErrorLogger
123123 mErrorList .clear ();
124124 }
125125
126- void openPlist (const std::string& filename, const std::vector<std::string>& files )
126+ void openPlist (const std::string& filename)
127127 {
128128 mPlistFile .open (filename);
129- mPlistFile << ErrorLogger::plistHeader (version (), files);
129+ mPlistFile << ErrorLogger::plistHeader (version ());
130+ }
131+
132+ void setPlistFilenames (std::vector<std::string> files)
133+ {
134+ if (mPlistFile .is_open ()) {
135+ mPlistFilenames = std::move (files);
136+ }
130137 }
131138
132139 void closePlist ()
133140 {
134141 if (mPlistFile .is_open ()) {
135- mPlistFile << ErrorLogger::plistFooter ();
142+ mPlistFile << ErrorLogger::plistFooter (mPlistFilenames );
136143 mPlistFile .close ();
144+ mPlistFilenames .clear ();
137145 }
138146 }
139147
@@ -276,6 +284,7 @@ class CppCheck::CppCheckLogger : public ErrorLogger
276284 std::map<Location, std::set<std::string>> mLocationMacros ; // What macros are used on a location?
277285
278286 std::ofstream mPlistFile ;
287+ std::vector<std::string> mPlistFilenames ;
279288
280289 unsigned int mExitCode {};
281290
@@ -986,9 +995,6 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str
986995
987996 Preprocessor preprocessor (mSettings , mErrorLogger , file.lang ());
988997
989- if (!preprocessor.loadFiles (tokens1, files))
990- return mLogger ->exitcode ();
991-
992998 if (!mSettings .plistOutput .empty ()) {
993999 std::string filename2;
9941000 if (file.spath ().find (' /' ) != std::string::npos)
@@ -997,23 +1003,18 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str
9971003 filename2 = file.spath ();
9981004 const std::size_t fileNameHash = std::hash<std::string> {}(file.spath ());
9991005 filename2 = mSettings .plistOutput + filename2.substr (0 , filename2.find (' .' )) + " _" + std::to_string (fileNameHash) + " .plist" ;
1000- mLogger ->openPlist (filename2, files );
1006+ mLogger ->openPlist (filename2);
10011007 }
10021008
1003- std::string dumpProlog ;
1009+ std::string dumpFooter ;
10041010 if (mSettings .dump || !mSettings .addons .empty ()) {
1005- dumpProlog += getDumpFileContentsRawTokens (files, tokens1);
1011+ dumpFooter += getDumpFileContentsRawTokensFooter ( tokens1);
10061012 }
10071013
10081014 // Parse comments and then remove them
1009- mLogger -> setRemarkComments ( preprocessor.getRemarkComments (tokens1));
1015+ preprocessor.addRemarkComments (tokens1, mLogger -> remarkComments ( ));
10101016 preprocessor.inlineSuppressions (tokens1, mSuppressions .nomsg );
1011- if (mSettings .dump || !mSettings .addons .empty ()) {
1012- std::ostringstream oss;
1013- mSuppressions .nomsg .dump (oss);
1014- dumpProlog += oss.str ();
1015- }
1016- preprocessor.removeComments (tokens1);
1017+ Preprocessor::removeComments (tokens1);
10171018
10181019 if (!mSettings .buildDir .empty ()) {
10191020 analyzerInformation.reset (new AnalyzerInformation);
@@ -1035,19 +1036,39 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str
10351036 }
10361037
10371038 // Get directives
1038- std::list<Directive> directives = preprocessor.createDirectives (tokens1);
1039- preprocessor.simplifyPragmaAsm (tokens1);
1039+ std::list<Directive> directives;
1040+ Preprocessor::createDirectives (tokens1, directives);
1041+ Preprocessor::simplifyPragmaAsm (tokens1);
1042+
1043+ // This needs to be a linked list to allow new configurations to be discovered
1044+ // and added while iterating and checking existing configurations
1045+ std::list<std::string> configurations;
1046+ std::set<std::string> configDefines = { " __cplusplus" };
1047+
1048+ preprocessor.setLoadCallback ([&](simplecpp::FileData& data) {
1049+ // Do preprocessing on included file
1050+ preprocessor.addRemarkComments (data.tokens , mLogger ->remarkComments ());
1051+ preprocessor.inlineSuppressions (data.tokens , mSuppressions .nomsg );
1052+ Preprocessor::removeComments (data.tokens );
1053+ Preprocessor::createDirectives (data.tokens , directives);
1054+ Preprocessor::simplifyPragmaAsm (data.tokens );
1055+ // Discover new configurations from included file
1056+ if ((mSettings .checkAllConfigurations && mSettings .userDefines .empty ()) || mSettings .force )
1057+ preprocessor.getConfigs (data.filename , data.tokens , configDefines, configurations);
1058+ });
10401059
10411060 Preprocessor::setPlatformInfo (tokens1, mSettings );
10421061
10431062 // Get configurations..
1044- std::set<std::string> configurations;
10451063 if ((mSettings .checkAllConfigurations && mSettings .userDefines .empty ()) || mSettings .force ) {
10461064 Timer::run (" Preprocessor::getConfigs" , mSettings .showtime , &s_timerResults, [&]() {
1047- configurations = preprocessor.getConfigs (tokens1);
1065+ configurations = { " " };
1066+ preprocessor.getConfigs (file.spath (), tokens1, configDefines, configurations);
1067+ preprocessor.loadFiles (tokens1, files);
1068+ configurations.sort ();
10481069 });
10491070 } else {
1050- configurations. insert ( mSettings .userDefines ) ;
1071+ configurations = { mSettings .userDefines } ;
10511072 }
10521073
10531074 if (mSettings .checkConfiguration ) {
@@ -1089,7 +1110,6 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str
10891110 createDumpFile (mSettings , file, fileIndex, fdump, dumpFile);
10901111 if (fdump.is_open ()) {
10911112 fdump << getLibraryDumpData ();
1092- fdump << dumpProlog;
10931113 if (!mSettings .dump )
10941114 filesDeleter.addFile (dumpFile);
10951115 }
@@ -1272,12 +1292,20 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str
12721292 }
12731293
12741294 // TODO: will not be closed if we encountered an exception
1275- // dumped all configs, close root </dumps> element now
12761295 if (fdump.is_open ()) {
1296+ // dump all filenames, raw tokens, suppressions
1297+ std::string dumpHeader = getDumpFileContentsRawTokensHeader (files);
1298+ fdump << getDumpFileContentsRawTokens (dumpHeader, dumpFooter);
1299+ mSuppressions .nomsg .dump (fdump);
1300+ // dumped all configs, close root </dumps> element now
12771301 fdump << " </dumps>" << std::endl;
12781302 fdump.close ();
12791303 }
12801304
1305+ if (!mSettings .plistOutput .empty ()) {
1306+ mLogger ->setPlistFilenames (std::move (files));
1307+ }
1308+
12811309 executeAddons (dumpFile, file);
12821310 } catch (const TerminateException &) {
12831311 // Analysis is terminated
@@ -1949,17 +1977,40 @@ bool CppCheck::isPremiumCodingStandardId(const std::string& id) const {
19491977 return false ;
19501978}
19511979
1952- std::string CppCheck::getDumpFileContentsRawTokens (const std::vector<std::string>& files, const simplecpp::TokenList& tokens1) const {
1980+ std::string CppCheck::getDumpFileContentsRawTokens (const std::vector<std::string>& files, const simplecpp::TokenList& tokens1) const
1981+ {
1982+ std::string header = getDumpFileContentsRawTokensHeader (files);
1983+ std::string footer = getDumpFileContentsRawTokensFooter (tokens1);
1984+ return getDumpFileContentsRawTokens (header, footer);
1985+ }
1986+
1987+ std::string CppCheck::getDumpFileContentsRawTokens (const std::string& header, const std::string& footer)
1988+ {
19531989 std::string dumpProlog;
19541990 dumpProlog += " <rawtokens>\n " ;
1991+ dumpProlog += header;
1992+ dumpProlog += footer;
1993+ dumpProlog += " </rawtokens>\n " ;
1994+ return dumpProlog;
1995+ }
1996+
1997+ std::string CppCheck::getDumpFileContentsRawTokensHeader (const std::vector<std::string>& files) const
1998+ {
1999+ std::string dumpProlog;
19552000 for (unsigned int i = 0 ; i < files.size (); ++i) {
19562001 dumpProlog += " <file index=\" " ;
19572002 dumpProlog += std::to_string (i);
19582003 dumpProlog += " \" name=\" " ;
19592004 dumpProlog += ErrorLogger::toxml (Path::getRelativePath (files[i], mSettings .basePaths ));
19602005 dumpProlog += " \" />\n " ;
19612006 }
1962- for (const simplecpp::Token *tok = tokens1.cfront (); tok; tok = tok->next ) {
2007+ return dumpProlog;
2008+ }
2009+
2010+ std::string CppCheck::getDumpFileContentsRawTokensFooter (const simplecpp::TokenList& tokens1)
2011+ {
2012+ std::string dumpProlog;
2013+ for (const simplecpp::Token* tok = tokens1.cfront (); tok; tok = tok->next ) {
19632014 dumpProlog += " <tok " ;
19642015
19652016 dumpProlog += " fileIndex=\" " ;
@@ -1970,7 +2021,7 @@ std::string CppCheck::getDumpFileContentsRawTokens(const std::vector<std::string
19702021 dumpProlog += std::to_string (tok->location .line );
19712022 dumpProlog += " \" " ;
19722023
1973- dumpProlog +=" column=\" " ;
2024+ dumpProlog += " column=\" " ;
19742025 dumpProlog += std::to_string (tok->location .col );
19752026 dumpProlog += " \" " ;
19762027
@@ -1980,6 +2031,5 @@ std::string CppCheck::getDumpFileContentsRawTokens(const std::vector<std::string
19802031
19812032 dumpProlog += " />\n " ;
19822033 }
1983- dumpProlog += " </rawtokens>\n " ;
19842034 return dumpProlog;
19852035}
0 commit comments