@@ -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,51 @@ 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+ // This needs to be a linked list to allow new configurations to be discovered
1049+ // and added while iterating and checking existing configurations
1050+ std::list<std::string> configurations;
1051+ std::set<std::string> configDefines = { " __cplusplus" };
1052+
1053+ // Insert library defines
1054+ for (const auto &define : mSettings .library .defines ()) {
1055+ const std::string::size_type paren = define.find (" (" );
1056+ const std::string::size_type space = define.find (" " );
1057+ std::string::size_type end = space;
1058+
1059+ if (paren != std::string::npos && paren < space)
1060+ end = paren;
1061+
1062+ configDefines.insert (define.substr (0 , end));
1063+ }
1064+
1065+ preprocessor.setLoadCallback ([&](simplecpp::FileData &data) {
1066+ // Do preprocessing on included file
1067+ preprocessor.addRemarkComments (data.tokens , mLogger ->remarkComments ());
1068+ preprocessor.inlineSuppressions (data.tokens , mSuppressions .nomsg );
1069+ preprocessor.removeComments (data.tokens );
1070+ preprocessor.createDirectives (data.tokens , directives);
1071+ preprocessor.simplifyPragmaAsm (data.tokens );
1072+ // Discover new configurations from included file
1073+ if (maxConfigs > 1 )
1074+ preprocessor.getConfigs (data.filename , data.tokens , configDefines, configurations);
1075+ });
1076+
10461077 preprocessor.setPlatformInfo ();
10471078
10481079 // Get configurations..
1049- std::set<std::string> configurations;
10501080 if (maxConfigs > 1 ) {
10511081 Timer::run (" Preprocessor::getConfigs" , mTimerResults , [&]() {
1052- configurations = preprocessor.getConfigs ();
1082+ configurations = { " " };
1083+ preprocessor.getConfigs (configDefines, configurations);
1084+ preprocessor.loadFiles (files);
1085+ configurations.sort ();
10531086 });
10541087 } else {
1055- configurations. insert ( mSettings .userDefines ) ;
1088+ configurations = { mSettings .userDefines } ;
10561089 }
10571090
10581091 if (mSettings .checkConfiguration ) {
@@ -1089,7 +1122,6 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str
10891122 createDumpFile (mSettings , file, fdump, dumpFile);
10901123 if (fdump.is_open ()) {
10911124 fdump << getLibraryDumpData ();
1092- fdump << dumpProlog;
10931125 if (!mSettings .dump )
10941126 filesDeleter.addFile (dumpFile);
10951127 }
@@ -1259,12 +1291,20 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str
12591291 }
12601292
12611293 // TODO: will not be closed if we encountered an exception
1262- // dumped all configs, close root </dumps> element now
12631294 if (fdump.is_open ()) {
1295+ // dump all filenames, raw tokens, suppressions
1296+ std::string dumpHeader = getDumpFileContentsRawTokensHeader (files);
1297+ fdump << getDumpFileContentsRawTokens (dumpHeader, dumpFooter);
1298+ mSuppressions .nomsg .dump (fdump);
1299+ // dumped all configs, close root </dumps> element now
12641300 fdump << " </dumps>" << std::endl;
12651301 fdump.close ();
12661302 }
12671303
1304+ if (!mSettings .plistOutput .empty ()) {
1305+ mLogger ->setPlistFilenames (std::move (files));
1306+ }
1307+
12681308 executeAddons (dumpFile, file);
12691309 } catch (const TerminateException &) {
12701310 // Analysis is terminated
@@ -1892,16 +1932,39 @@ bool CppCheck::isPremiumCodingStandardId(const std::string& id) const {
18921932 return false ;
18931933}
18941934
1895- std::string CppCheck::getDumpFileContentsRawTokens (const std::vector<std::string>& files, const simplecpp::TokenList& tokens1) const {
1935+ std::string CppCheck::getDumpFileContentsRawTokens (const std::vector<std::string>& files, const simplecpp::TokenList& tokens1) const
1936+ {
1937+ std::string header = getDumpFileContentsRawTokensHeader (files);
1938+ std::string footer = getDumpFileContentsRawTokensFooter (tokens1);
1939+ return getDumpFileContentsRawTokens (header, footer);
1940+ }
1941+
1942+ std::string CppCheck::getDumpFileContentsRawTokens (const std::string& header, const std::string& footer)
1943+ {
18961944 std::string dumpProlog;
18971945 dumpProlog += " <rawtokens>\n " ;
1946+ dumpProlog += header;
1947+ dumpProlog += footer;
1948+ dumpProlog += " </rawtokens>\n " ;
1949+ return dumpProlog;
1950+ }
1951+
1952+ std::string CppCheck::getDumpFileContentsRawTokensHeader (const std::vector<std::string>& files) const
1953+ {
1954+ std::string dumpProlog;
18981955 for (unsigned int i = 0 ; i < files.size (); ++i) {
18991956 dumpProlog += " <file index=\" " ;
19001957 dumpProlog += std::to_string (i);
19011958 dumpProlog += " \" name=\" " ;
19021959 dumpProlog += ErrorLogger::toxml (Path::getRelativePath (files[i], mSettings .basePaths ));
19031960 dumpProlog += " \" />\n " ;
19041961 }
1962+ return dumpProlog;
1963+ }
1964+
1965+ std::string CppCheck::getDumpFileContentsRawTokensFooter (const simplecpp::TokenList& tokens1)
1966+ {
1967+ std::string dumpProlog;
19051968 for (const simplecpp::Token *tok = tokens1.cfront (); tok; tok = tok->next ) {
19061969 dumpProlog += " <tok " ;
19071970
@@ -1913,7 +1976,7 @@ std::string CppCheck::getDumpFileContentsRawTokens(const std::vector<std::string
19131976 dumpProlog += std::to_string (tok->location .line );
19141977 dumpProlog += " \" " ;
19151978
1916- dumpProlog +=" column=\" " ;
1979+ dumpProlog += " column=\" " ;
19171980 dumpProlog += std::to_string (tok->location .col );
19181981 dumpProlog += " \" " ;
19191982
@@ -1923,6 +1986,5 @@ std::string CppCheck::getDumpFileContentsRawTokens(const std::vector<std::string
19231986
19241987 dumpProlog += " />\n " ;
19251988 }
1926- dumpProlog += " </rawtokens>\n " ;
19271989 return dumpProlog;
19281990}
0 commit comments