6161#include < exception> // IWYU pragma: keep
6262#include < fstream>
6363#include < iostream>
64+ #include < iterator>
6465#include < map>
6566#include < new>
6667#include < set>
@@ -100,9 +101,9 @@ class CppCheck::CppCheckLogger : public ErrorLogger
100101 closePlist ();
101102 }
102103
103- void setRemarkComments ( std::vector<RemarkComment> remarkComments)
104+ void addRemarkComments ( const std::vector<RemarkComment> & remarkComments)
104105 {
105- mRemarkComments = std::move ( remarkComments);
106+ mRemarkComments . insert ( mRemarkComments . end (), remarkComments. begin (), remarkComments. end () );
106107 }
107108
108109 void setLocationMacros (const Token* startTok, const std::vector<std::string>& files)
@@ -124,17 +125,25 @@ class CppCheck::CppCheckLogger : public ErrorLogger
124125 mErrorList .clear ();
125126 }
126127
127- void openPlist (const std::string& filename, const std::vector<std::string>& files )
128+ void openPlist (const std::string& filename)
128129 {
129130 mPlistFile .open (filename);
130- mPlistFile << ErrorLogger::plistHeader (version (), files);
131+ mPlistFile << ErrorLogger::plistHeader (version ());
132+ }
133+
134+ void setPlistFilenames (std::vector<std::string> files)
135+ {
136+ if (mPlistFile .is_open ()) {
137+ mPlistFilenames = std::move (files);
138+ }
131139 }
132140
133141 void closePlist ()
134142 {
135143 if (mPlistFile .is_open ()) {
136- mPlistFile << ErrorLogger::plistFooter ();
144+ mPlistFile << ErrorLogger::plistFooter (mPlistFilenames );
137145 mPlistFile .close ();
146+ mPlistFilenames .clear ();
138147 }
139148 }
140149
@@ -282,6 +291,7 @@ class CppCheck::CppCheckLogger : public ErrorLogger
282291 std::map<Location, std::set<std::string>> mLocationMacros ; // What macros are used on a location?
283292
284293 std::ofstream mPlistFile ;
294+ std::vector<std::string> mPlistFilenames ;
285295
286296 unsigned int mExitCode {};
287297
@@ -898,7 +908,7 @@ unsigned int CppCheck::checkFile(const FileWithDetails& file, const std::string
898908 return checkInternal (file, cfgname, f);
899909}
900910
901- void CppCheck::checkPlistOutput (const FileWithDetails& file, const std::vector<std::string>& files )
911+ void CppCheck::checkPlistOutput (const FileWithDetails& file)
902912{
903913 if (!mSettings .plistOutput .empty ()) {
904914 const bool slashFound = file.spath ().find (' /' ) != std::string::npos;
@@ -909,7 +919,7 @@ void CppCheck::checkPlistOutput(const FileWithDetails& file, const std::vector<s
909919 // the hash is added to handle when files in different folders have the same name
910920 const std::size_t fileNameHash = std::hash<std::string> {}(file.spath ());
911921 filename = mSettings .plistOutput + noSuffixFilename + " _" + std::to_string (fileNameHash) + " .plist" ;
912- mLogger ->openPlist (filename, files );
922+ mLogger ->openPlist (filename);
913923 }
914924}
915925
@@ -1000,24 +1010,16 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str
10001010 if (preprocessor.reportOutput (outputList, true ))
10011011 return mLogger ->exitcode ();
10021012
1003- if (!preprocessor.loadFiles (files))
1004- return mLogger ->exitcode ();
1005-
1006- checkPlistOutput (file, files);
1013+ checkPlistOutput (file);
10071014
1008- std::string dumpProlog ;
1015+ std::string dumpFooter ;
10091016 if (mSettings .dump || !mSettings .addons .empty ()) {
1010- dumpProlog += getDumpFileContentsRawTokens (files, tokens1);
1017+ dumpFooter += getDumpFileContentsRawTokensFooter ( tokens1);
10111018 }
10121019
10131020 // Parse comments and then remove them
1014- mLogger ->setRemarkComments (preprocessor.getRemarkComments ());
1021+ mLogger ->addRemarkComments (preprocessor.getRemarkComments ());
10151022 preprocessor.inlineSuppressions (mSuppressions .nomsg );
1016- if (mSettings .dump || !mSettings .addons .empty ()) {
1017- std::ostringstream oss;
1018- mSuppressions .nomsg .dump (oss);
1019- dumpProlog += oss.str ();
1020- }
10211023 preprocessor.removeComments ();
10221024
10231025 if (!mSettings .buildDir .empty ()) {
@@ -1040,19 +1042,45 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str
10401042 }
10411043
10421044 // Get directives
1043- std::list<Directive> directives = preprocessor.createDirectives ();
1045+ std::list<Directive> directives;
1046+ preprocessor.createDirectives (directives);
10441047 preprocessor.simplifyPragmaAsm ();
10451048
1049+ std::set<std::string> configurations;
1050+ std::set<std::string> configDefines = { " __cplusplus" };
1051+
1052+ // Insert library defines
1053+ const auto getDefineName = [](const std::string &defineString) {
1054+ return defineString.substr (0 , defineString.find_first_of (" ( " ));
1055+ };
1056+ std::transform (mSettings .library .defines ().begin (),
1057+ mSettings .library .defines ().end (),
1058+ std::inserter (configDefines, configDefines.end ()),
1059+ getDefineName);
1060+
1061+ preprocessor.setLoadCallback ([&](simplecpp::FileData &data) {
1062+ // Do preprocessing on included file
1063+ mLogger ->addRemarkComments (preprocessor.getRemarkComments (data.tokens ));
1064+ preprocessor.inlineSuppressions (data.tokens , mSuppressions .nomsg );
1065+ Preprocessor::removeComments (data.tokens );
1066+ Preprocessor::createDirectives (data.tokens , directives);
1067+ Preprocessor::simplifyPragmaAsm (data.tokens );
1068+ // Discover new configurations from included file
1069+ if (configurations.size () < maxConfigs)
1070+ preprocessor.getConfigs (data.filename , data.tokens , configDefines, configurations);
1071+ });
1072+
10461073 preprocessor.setPlatformInfo ();
10471074
10481075 // Get configurations..
1049- std::set<std::string> configurations;
10501076 if (maxConfigs > 1 ) {
10511077 Timer::run (" Preprocessor::getConfigs" , mTimerResults , [&]() {
1052- configurations = preprocessor.getConfigs ();
1078+ configurations = { " " };
1079+ preprocessor.getConfigs (configDefines, configurations);
1080+ preprocessor.loadFiles (files);
10531081 });
10541082 } else {
1055- configurations. insert ( mSettings .userDefines ) ;
1083+ configurations = { mSettings .userDefines } ;
10561084 }
10571085
10581086 if (mSettings .checkConfiguration ) {
@@ -1089,7 +1117,6 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str
10891117 createDumpFile (mSettings , file, fdump, dumpFile);
10901118 if (fdump.is_open ()) {
10911119 fdump << getLibraryDumpData ();
1092- fdump << dumpProlog;
10931120 if (!mSettings .dump )
10941121 filesDeleter.addFile (dumpFile);
10951122 }
@@ -1259,12 +1286,20 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str
12591286 }
12601287
12611288 // TODO: will not be closed if we encountered an exception
1262- // dumped all configs, close root </dumps> element now
12631289 if (fdump.is_open ()) {
1290+ // dump all filenames, raw tokens, suppressions
1291+ std::string dumpHeader = getDumpFileContentsRawTokensHeader (files);
1292+ fdump << getDumpFileContentsRawTokens (dumpHeader, dumpFooter);
1293+ mSuppressions .nomsg .dump (fdump);
1294+ // dumped all configs, close root </dumps> element now
12641295 fdump << " </dumps>" << std::endl;
12651296 fdump.close ();
12661297 }
12671298
1299+ if (!mSettings .plistOutput .empty ()) {
1300+ mLogger ->setPlistFilenames (std::move (files));
1301+ }
1302+
12681303 executeAddons (dumpFile, file);
12691304 } catch (const TerminateException &) {
12701305 // Analysis is terminated
@@ -1892,16 +1927,39 @@ bool CppCheck::isPremiumCodingStandardId(const std::string& id) const {
18921927 return false ;
18931928}
18941929
1895- std::string CppCheck::getDumpFileContentsRawTokens (const std::vector<std::string>& files, const simplecpp::TokenList& tokens1) const {
1930+ std::string CppCheck::getDumpFileContentsRawTokens (const std::vector<std::string>& files, const simplecpp::TokenList& tokens1) const
1931+ {
1932+ std::string header = getDumpFileContentsRawTokensHeader (files);
1933+ std::string footer = getDumpFileContentsRawTokensFooter (tokens1);
1934+ return getDumpFileContentsRawTokens (header, footer);
1935+ }
1936+
1937+ std::string CppCheck::getDumpFileContentsRawTokens (const std::string& header, const std::string& footer)
1938+ {
18961939 std::string dumpProlog;
18971940 dumpProlog += " <rawtokens>\n " ;
1941+ dumpProlog += header;
1942+ dumpProlog += footer;
1943+ dumpProlog += " </rawtokens>\n " ;
1944+ return dumpProlog;
1945+ }
1946+
1947+ std::string CppCheck::getDumpFileContentsRawTokensHeader (const std::vector<std::string>& files) const
1948+ {
1949+ std::string dumpProlog;
18981950 for (unsigned int i = 0 ; i < files.size (); ++i) {
18991951 dumpProlog += " <file index=\" " ;
19001952 dumpProlog += std::to_string (i);
19011953 dumpProlog += " \" name=\" " ;
19021954 dumpProlog += ErrorLogger::toxml (Path::getRelativePath (files[i], mSettings .basePaths ));
19031955 dumpProlog += " \" />\n " ;
19041956 }
1957+ return dumpProlog;
1958+ }
1959+
1960+ std::string CppCheck::getDumpFileContentsRawTokensFooter (const simplecpp::TokenList& tokens1)
1961+ {
1962+ std::string dumpProlog;
19051963 for (const simplecpp::Token *tok = tokens1.cfront (); tok; tok = tok->next ) {
19061964 dumpProlog += " <tok " ;
19071965
@@ -1913,7 +1971,7 @@ std::string CppCheck::getDumpFileContentsRawTokens(const std::vector<std::string
19131971 dumpProlog += std::to_string (tok->location .line );
19141972 dumpProlog += " \" " ;
19151973
1916- dumpProlog +=" column=\" " ;
1974+ dumpProlog += " column=\" " ;
19171975 dumpProlog += std::to_string (tok->location .col );
19181976 dumpProlog += " \" " ;
19191977
@@ -1923,6 +1981,5 @@ std::string CppCheck::getDumpFileContentsRawTokens(const std::vector<std::string
19231981
19241982 dumpProlog += " />\n " ;
19251983 }
1926- dumpProlog += " </rawtokens>\n " ;
19271984 return dumpProlog;
19281985}
0 commit comments