Skip to content

Commit 7d27583

Browse files
committed
14113
1 parent 86f4c91 commit 7d27583

13 files changed

Lines changed: 261 additions & 159 deletions

File tree

.github/workflows/selfcheck.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ jobs:
121121
122122
- name: Self check (unusedFunction / no test / no gui)
123123
run: |
124-
supprs="--suppress=unusedFunction:lib/errorlogger.h:197 --suppress=unusedFunction:lib/importproject.cpp:1671 --suppress=unusedFunction:lib/importproject.cpp:1695"
124+
supprs="--suppress=unusedFunction:lib/errorlogger.h:198 --suppress=unusedFunction:lib/importproject.cpp:1671 --suppress=unusedFunction:lib/importproject.cpp:1695"
125125
./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib -D__CPPCHECK__ -D__GNUC__ --enable=unusedFunction,information --exception-handling -rp=. --project=cmake.output.notest_nogui/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr $supprs
126126
env:
127127
DISABLE_VALUEFLOW: 1

externals/simplecpp/simplecpp.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3113,6 +3113,9 @@ std::pair<simplecpp::FileData *, bool> simplecpp::FileDataCache::tryload(FileDat
31133113
mIdMap.emplace(fileId, data);
31143114
mData.emplace_back(data);
31153115

3116+
if (mCallback)
3117+
mCallback(*data);
3118+
31163119
return {data, true};
31173120
}
31183121

externals/simplecpp/simplecpp.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <cctype>
1010
#include <cstdint>
1111
#include <cstring>
12+
#include <functional>
1213
#include <iosfwd>
1314
#include <list>
1415
#include <map>
@@ -505,6 +506,12 @@ namespace simplecpp {
505506
return mData.cend();
506507
}
507508

509+
using callback_type = std::function<void (FileData &)>;
510+
511+
void set_callback(callback_type cb) {
512+
mCallback = std::move(cb);
513+
}
514+
508515
private:
509516
struct FileID {
510517
#ifdef _WIN32
@@ -551,6 +558,7 @@ namespace simplecpp {
551558
container_type mData;
552559
name_map_type mNameMap;
553560
id_map_type mIdMap;
561+
callback_type mCallback;
554562
};
555563

556564
/** Converts character literal (including prefix, but not ud-suffix) to long long value.

lib/cppcheck.cpp

Lines changed: 91 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}

lib/cppcheck.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,9 @@ class CPPCHECKLIB CppCheck {
153153
* @brief Get dumpfile <rawtokens> contents, this is only public for testing purposes
154154
*/
155155
std::string getDumpFileContentsRawTokens(const std::vector<std::string>& files, const simplecpp::TokenList& tokens1) const;
156+
static std::string getDumpFileContentsRawTokens(const std::string& header, const std::string& footer);
157+
std::string getDumpFileContentsRawTokensHeader(const std::vector<std::string>& files) const;
158+
static std::string getDumpFileContentsRawTokensFooter(const simplecpp::TokenList& tokens1);
156159

157160
std::string getLibraryDumpData() const;
158161

@@ -183,7 +186,7 @@ class CPPCHECKLIB CppCheck {
183186
*/
184187
unsigned int checkFile(const FileWithDetails& file, const std::string &cfgname);
185188

186-
void checkPlistOutput(const FileWithDetails& file, const std::vector<std::string>& files);
189+
void checkPlistOutput(const FileWithDetails& file);
187190

188191
/**
189192
* @brief Check a file using buffer

lib/errorlogger.cpp

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -821,20 +821,15 @@ std::string ErrorLogger::toxml(const std::string &str)
821821
return xml;
822822
}
823823

824-
std::string ErrorLogger::plistHeader(const std::string &version, const std::vector<std::string> &files)
824+
std::string ErrorLogger::plistHeader(const std::string &version)
825825
{
826826
std::ostringstream ostr;
827827
ostr << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
828828
<< "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\r\n"
829829
<< "<plist version=\"1.0\">\r\n"
830830
<< "<dict>\r\n"
831831
<< " <key>clang_version</key>\r\n"
832-
<< "<string>cppcheck version " << version << "</string>\r\n"
833-
<< " <key>files</key>\r\n"
834-
<< " <array>\r\n";
835-
for (const std::string & file : files)
836-
ostr << " <string>" << ErrorLogger::toxml(file) << "</string>\r\n";
837-
ostr << " </array>\r\n"
832+
<< " <string>cppcheck version " << version << "</string>\r\n"
838833
<< " <key>diagnostics</key>\r\n"
839834
<< " <array>\r\n";
840835
return ostr.str();

lib/errorlogger.h

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <ctime>
2929
#include <list>
3030
#include <set>
31+
#include <sstream>
3132
#include <string>
3233
#include <utility>
3334
#include <vector>
@@ -271,12 +272,19 @@ class CPPCHECKLIB ErrorLogger {
271272
*/
272273
static std::string toxml(const std::string &str);
273274

274-
static std::string plistHeader(const std::string &version, const std::vector<std::string> &files);
275+
static std::string plistHeader(const std::string &version);
275276
static std::string plistData(const ErrorMessage &msg);
276-
static const char *plistFooter() {
277-
return " </array>\r\n"
278-
"</dict>\r\n"
279-
"</plist>";
277+
static std::string plistFooter(const std::vector<std::string>& files) {
278+
std::ostringstream ostr;
279+
ostr << " </array>\r\n"
280+
<< " <key>files</key>\r\n"
281+
<< " <array>\r\n";
282+
for (const std::string& file : files)
283+
ostr << " <string>" << ErrorLogger::toxml(file) << "</string>\r\n";
284+
ostr << " </array>\r\n"
285+
<< "</dict>\r\n"
286+
<< "</plist>";
287+
return ostr.str();
280288
}
281289

282290
static bool isCriticalErrorId(const std::string& id) {

0 commit comments

Comments
 (0)