@@ -100,9 +100,9 @@ class CppCheck::CppCheckLogger : public ErrorLogger
100100 closePlist ();
101101 }
102102
103- void setRemarkComments ( std::vector<RemarkComment> remarkComments)
103+ std::vector<RemarkComment>& remarkComments ( )
104104 {
105- mRemarkComments = std::move (remarkComments) ;
105+ return mRemarkComments ;
106106 }
107107
108108 void setLocationMacros (const Token* startTok, const std::vector<std::string>& files)
@@ -124,17 +124,25 @@ class CppCheck::CppCheckLogger : public ErrorLogger
124124 mErrorList .clear ();
125125 }
126126
127- void openPlist (const std::string& filename, const std::vector<std::string>& files )
127+ void openPlist (const std::string& filename)
128128 {
129129 mPlistFile .open (filename);
130- mPlistFile << ErrorLogger::plistHeader (version (), files);
130+ mPlistFile << ErrorLogger::plistHeader (version ());
131+ }
132+
133+ void setPlistFilenames (std::vector<std::string> files)
134+ {
135+ if (mPlistFile .is_open ()) {
136+ mPlistFilenames = std::move (files);
137+ }
131138 }
132139
133140 void closePlist ()
134141 {
135142 if (mPlistFile .is_open ()) {
136- mPlistFile << ErrorLogger::plistFooter ();
143+ mPlistFile << ErrorLogger::plistFooter (mPlistFilenames );
137144 mPlistFile .close ();
145+ mPlistFilenames .clear ();
138146 }
139147 }
140148
@@ -282,6 +290,7 @@ class CppCheck::CppCheckLogger : public ErrorLogger
282290 std::map<Location, std::set<std::string>> mLocationMacros ; // What macros are used on a location?
283291
284292 std::ofstream mPlistFile ;
293+ std::vector<std::string> mPlistFilenames ;
285294
286295 unsigned int mExitCode {};
287296
@@ -898,7 +907,7 @@ unsigned int CppCheck::checkFile(const FileWithDetails& file, const std::string
898907 return checkInternal (file, cfgname, f);
899908}
900909
901- void CppCheck::checkPlistOutput (const FileWithDetails& file, const std::vector<std::string>& files )
910+ void CppCheck::checkPlistOutput (const FileWithDetails& file)
902911{
903912 if (!mSettings .plistOutput .empty ()) {
904913 const bool slashFound = file.spath ().find (' /' ) != std::string::npos;
@@ -909,7 +918,7 @@ void CppCheck::checkPlistOutput(const FileWithDetails& file, const std::vector<s
909918 // the hash is added to handle when files in different folders have the same name
910919 const std::size_t fileNameHash = std::hash<std::string> {}(file.spath ());
911920 filename = mSettings .plistOutput + noSuffixFilename + " _" + std::to_string (fileNameHash) + " .plist" ;
912- mLogger ->openPlist (filename, files );
921+ mLogger ->openPlist (filename);
913922 }
914923}
915924
@@ -1000,24 +1009,16 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str
10001009 if (preprocessor.reportOutput (outputList, true ))
10011010 return mLogger ->exitcode ();
10021011
1003- if (!preprocessor.loadFiles (files))
1004- return mLogger ->exitcode ();
1005-
1006- checkPlistOutput (file, files);
1012+ checkPlistOutput (file);
10071013
1008- std::string dumpProlog ;
1014+ std::string dumpFooter ;
10091015 if (mSettings .dump || !mSettings .addons .empty ()) {
1010- dumpProlog += getDumpFileContentsRawTokens (files, tokens1);
1016+ dumpFooter += getDumpFileContentsRawTokensFooter ( tokens1);
10111017 }
10121018
10131019 // Parse comments and then remove them
1014- mLogger ->setRemarkComments (preprocessor. getRemarkComments ());
1020+ preprocessor. addRemarkComments ( mLogger ->remarkComments ());
10151021 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- }
10211022 preprocessor.removeComments ();
10221023
10231024 if (!mSettings .buildDir .empty ()) {
@@ -1040,19 +1041,48 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str
10401041 }
10411042
10421043 // Get directives
1043- std::list<Directive> directives = preprocessor.createDirectives ();
1044+ std::list<Directive> directives;
1045+ preprocessor.createDirectives (directives);
10441046 preprocessor.simplifyPragmaAsm ();
10451047
1048+ std::set<std::string> configurations;
1049+ std::set<std::string> configDefines = { " __cplusplus" };
1050+
1051+ // Insert library defines
1052+ for (const auto &define : mSettings .library .defines ()) {
1053+ const std::string::size_type paren = define.find (" (" );
1054+ const std::string::size_type space = define.find (" " );
1055+ std::string::size_type end = space;
1056+
1057+ if (paren != std::string::npos && paren < space)
1058+ end = paren;
1059+
1060+ configDefines.insert (define.substr (0 , end));
1061+ }
1062+
1063+ preprocessor.setLoadCallback ([&](simplecpp::FileData &data) {
1064+ // Do preprocessing on included file
1065+ preprocessor.addRemarkComments (data.tokens , mLogger ->remarkComments ());
1066+ preprocessor.inlineSuppressions (data.tokens , mSuppressions .nomsg );
1067+ Preprocessor::removeComments (data.tokens );
1068+ Preprocessor::createDirectives (data.tokens , directives);
1069+ Preprocessor::simplifyPragmaAsm (data.tokens );
1070+ // Discover new configurations from included file
1071+ if (configurations.size () < maxConfigs)
1072+ preprocessor.getConfigs (data.filename , data.tokens , configDefines, configurations);
1073+ });
1074+
10461075 preprocessor.setPlatformInfo ();
10471076
10481077 // Get configurations..
1049- std::set<std::string> configurations;
10501078 if (maxConfigs > 1 ) {
10511079 Timer::run (" Preprocessor::getConfigs" , mTimerResults , [&]() {
1052- configurations = preprocessor.getConfigs ();
1080+ configurations = { " " };
1081+ preprocessor.getConfigs (configDefines, configurations);
1082+ preprocessor.loadFiles (files);
10531083 });
10541084 } else {
1055- configurations. insert ( mSettings .userDefines ) ;
1085+ configurations = { mSettings .userDefines } ;
10561086 }
10571087
10581088 if (mSettings .checkConfiguration ) {
@@ -1089,7 +1119,6 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str
10891119 createDumpFile (mSettings , file, fdump, dumpFile);
10901120 if (fdump.is_open ()) {
10911121 fdump << getLibraryDumpData ();
1092- fdump << dumpProlog;
10931122 if (!mSettings .dump )
10941123 filesDeleter.addFile (dumpFile);
10951124 }
@@ -1259,12 +1288,20 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str
12591288 }
12601289
12611290 // TODO: will not be closed if we encountered an exception
1262- // dumped all configs, close root </dumps> element now
12631291 if (fdump.is_open ()) {
1292+ // dump all filenames, raw tokens, suppressions
1293+ std::string dumpHeader = getDumpFileContentsRawTokensHeader (files);
1294+ fdump << getDumpFileContentsRawTokens (dumpHeader, dumpFooter);
1295+ mSuppressions .nomsg .dump (fdump);
1296+ // dumped all configs, close root </dumps> element now
12641297 fdump << " </dumps>" << std::endl;
12651298 fdump.close ();
12661299 }
12671300
1301+ if (!mSettings .plistOutput .empty ()) {
1302+ mLogger ->setPlistFilenames (std::move (files));
1303+ }
1304+
12681305 executeAddons (dumpFile, file);
12691306 } catch (const TerminateException &) {
12701307 // Analysis is terminated
@@ -1892,16 +1929,39 @@ bool CppCheck::isPremiumCodingStandardId(const std::string& id) const {
18921929 return false ;
18931930}
18941931
1895- std::string CppCheck::getDumpFileContentsRawTokens (const std::vector<std::string>& files, const simplecpp::TokenList& tokens1) const {
1932+ std::string CppCheck::getDumpFileContentsRawTokens (const std::vector<std::string>& files, const simplecpp::TokenList& tokens1) const
1933+ {
1934+ std::string header = getDumpFileContentsRawTokensHeader (files);
1935+ std::string footer = getDumpFileContentsRawTokensFooter (tokens1);
1936+ return getDumpFileContentsRawTokens (header, footer);
1937+ }
1938+
1939+ std::string CppCheck::getDumpFileContentsRawTokens (const std::string& header, const std::string& footer)
1940+ {
18961941 std::string dumpProlog;
18971942 dumpProlog += " <rawtokens>\n " ;
1943+ dumpProlog += header;
1944+ dumpProlog += footer;
1945+ dumpProlog += " </rawtokens>\n " ;
1946+ return dumpProlog;
1947+ }
1948+
1949+ std::string CppCheck::getDumpFileContentsRawTokensHeader (const std::vector<std::string>& files) const
1950+ {
1951+ std::string dumpProlog;
18981952 for (unsigned int i = 0 ; i < files.size (); ++i) {
18991953 dumpProlog += " <file index=\" " ;
19001954 dumpProlog += std::to_string (i);
19011955 dumpProlog += " \" name=\" " ;
19021956 dumpProlog += ErrorLogger::toxml (Path::getRelativePath (files[i], mSettings .basePaths ));
19031957 dumpProlog += " \" />\n " ;
19041958 }
1959+ return dumpProlog;
1960+ }
1961+
1962+ std::string CppCheck::getDumpFileContentsRawTokensFooter (const simplecpp::TokenList& tokens1)
1963+ {
1964+ std::string dumpProlog;
19051965 for (const simplecpp::Token *tok = tokens1.cfront (); tok; tok = tok->next ) {
19061966 dumpProlog += " <tok " ;
19071967
@@ -1913,7 +1973,7 @@ std::string CppCheck::getDumpFileContentsRawTokens(const std::vector<std::string
19131973 dumpProlog += std::to_string (tok->location .line );
19141974 dumpProlog += " \" " ;
19151975
1916- dumpProlog +=" column=\" " ;
1976+ dumpProlog += " column=\" " ;
19171977 dumpProlog += std::to_string (tok->location .col );
19181978 dumpProlog += " \" " ;
19191979
@@ -1923,6 +1983,5 @@ std::string CppCheck::getDumpFileContentsRawTokens(const std::vector<std::string
19231983
19241984 dumpProlog += " />\n " ;
19251985 }
1926- dumpProlog += " </rawtokens>\n " ;
19271986 return dumpProlog;
19281987}
0 commit comments