@@ -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,52 @@ 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+ // cppcheck-suppress danglingLifetime - false positive: lambda is owned by preprocessor
1066+ preprocessor.setLoadCallback ([&](simplecpp::FileData &data) {
1067+ // Do preprocessing on included file
1068+ preprocessor.addRemarkComments (data.tokens , mLogger ->remarkComments ());
1069+ preprocessor.inlineSuppressions (data.tokens , mSuppressions .nomsg );
1070+ Preprocessor::removeComments (data.tokens );
1071+ Preprocessor::createDirectives (data.tokens , directives);
1072+ Preprocessor::simplifyPragmaAsm (data.tokens );
1073+ // Discover new configurations from included file
1074+ if (maxConfigs > 1 )
1075+ preprocessor.getConfigs (data.filename , data.tokens , configDefines, configurations);
1076+ });
1077+
10461078 preprocessor.setPlatformInfo ();
10471079
10481080 // Get configurations..
1049- std::set<std::string> configurations;
10501081 if (maxConfigs > 1 ) {
10511082 Timer::run (" Preprocessor::getConfigs" , mTimerResults , [&]() {
1052- configurations = preprocessor.getConfigs ();
1083+ configurations = { " " };
1084+ preprocessor.getConfigs (configDefines, configurations);
1085+ preprocessor.loadFiles (files);
1086+ configurations.sort ();
10531087 });
10541088 } else {
1055- configurations. insert ( mSettings .userDefines ) ;
1089+ configurations = { mSettings .userDefines } ;
10561090 }
10571091
10581092 if (mSettings .checkConfiguration ) {
@@ -1089,7 +1123,6 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str
10891123 createDumpFile (mSettings , file, fdump, dumpFile);
10901124 if (fdump.is_open ()) {
10911125 fdump << getLibraryDumpData ();
1092- fdump << dumpProlog;
10931126 if (!mSettings .dump )
10941127 filesDeleter.addFile (dumpFile);
10951128 }
@@ -1259,12 +1292,20 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str
12591292 }
12601293
12611294 // TODO: will not be closed if we encountered an exception
1262- // dumped all configs, close root </dumps> element now
12631295 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
12641301 fdump << " </dumps>" << std::endl;
12651302 fdump.close ();
12661303 }
12671304
1305+ if (!mSettings .plistOutput .empty ()) {
1306+ mLogger ->setPlistFilenames (std::move (files));
1307+ }
1308+
12681309 executeAddons (dumpFile, file);
12691310 } catch (const TerminateException &) {
12701311 // Analysis is terminated
@@ -1892,16 +1933,39 @@ bool CppCheck::isPremiumCodingStandardId(const std::string& id) const {
18921933 return false ;
18931934}
18941935
1895- std::string CppCheck::getDumpFileContentsRawTokens (const std::vector<std::string>& files, const simplecpp::TokenList& tokens1) const {
1936+ std::string CppCheck::getDumpFileContentsRawTokens (const std::vector<std::string>& files, const simplecpp::TokenList& tokens1) const
1937+ {
1938+ std::string header = getDumpFileContentsRawTokensHeader (files);
1939+ std::string footer = getDumpFileContentsRawTokensFooter (tokens1);
1940+ return getDumpFileContentsRawTokens (header, footer);
1941+ }
1942+
1943+ std::string CppCheck::getDumpFileContentsRawTokens (const std::string& header, const std::string& footer)
1944+ {
18961945 std::string dumpProlog;
18971946 dumpProlog += " <rawtokens>\n " ;
1947+ dumpProlog += header;
1948+ dumpProlog += footer;
1949+ dumpProlog += " </rawtokens>\n " ;
1950+ return dumpProlog;
1951+ }
1952+
1953+ std::string CppCheck::getDumpFileContentsRawTokensHeader (const std::vector<std::string>& files) const
1954+ {
1955+ std::string dumpProlog;
18981956 for (unsigned int i = 0 ; i < files.size (); ++i) {
18991957 dumpProlog += " <file index=\" " ;
19001958 dumpProlog += std::to_string (i);
19011959 dumpProlog += " \" name=\" " ;
19021960 dumpProlog += ErrorLogger::toxml (Path::getRelativePath (files[i], mSettings .basePaths ));
19031961 dumpProlog += " \" />\n " ;
19041962 }
1963+ return dumpProlog;
1964+ }
1965+
1966+ std::string CppCheck::getDumpFileContentsRawTokensFooter (const simplecpp::TokenList& tokens1)
1967+ {
1968+ std::string dumpProlog;
19051969 for (const simplecpp::Token *tok = tokens1.cfront (); tok; tok = tok->next ) {
19061970 dumpProlog += " <tok " ;
19071971
@@ -1913,7 +1977,7 @@ std::string CppCheck::getDumpFileContentsRawTokens(const std::vector<std::string
19131977 dumpProlog += std::to_string (tok->location .line );
19141978 dumpProlog += " \" " ;
19151979
1916- dumpProlog +=" column=\" " ;
1980+ dumpProlog += " column=\" " ;
19171981 dumpProlog += std::to_string (tok->location .col );
19181982 dumpProlog += " \" " ;
19191983
@@ -1923,6 +1987,5 @@ std::string CppCheck::getDumpFileContentsRawTokens(const std::vector<std::string
19231987
19241988 dumpProlog += " />\n " ;
19251989 }
1926- dumpProlog += " </rawtokens>\n " ;
19271990 return dumpProlog;
19281991}
0 commit comments