Skip to content

Commit 28182fb

Browse files
committed
14974
1 parent 2e19539 commit 28182fb

11 files changed

Lines changed: 140 additions & 48 deletions

File tree

externals/simplecpp/simplecpp.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3154,13 +3154,10 @@ std::pair<simplecpp::FileData *, bool> simplecpp::FileDataCache::tryload(FileDat
31543154
mImpl->mIdMap.emplace(fileId, data);
31553155
mData.emplace_back(data);
31563156

3157-
if (mLoadCallback)
3158-
mLoadCallback(*data);
3159-
31603157
return {data, true};
31613158
}
31623159

3163-
std::pair<simplecpp::FileData *, bool> simplecpp::FileDataCache::get(const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader, std::vector<std::string> &filenames, simplecpp::OutputList *outputList)
3160+
std::pair<simplecpp::FileData *, bool> simplecpp::FileDataCache::get_private(const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader, std::vector<std::string> &filenames, simplecpp::OutputList *outputList)
31643161
{
31653162
if (isAbsolutePath(header)) {
31663163
auto ins = mNameMap.emplace(simplecpp::simplifyPath(header), nullptr);
@@ -3206,6 +3203,16 @@ std::pair<simplecpp::FileData *, bool> simplecpp::FileDataCache::get(const std::
32063203
return {nullptr, false};
32073204
}
32083205

3206+
std::pair<simplecpp::FileData *, bool> simplecpp::FileDataCache::get(const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader, std::vector<std::string> &filenames, simplecpp::OutputList *outputList)
3207+
{
3208+
auto ret = get_private(sourcefile, header, dui, systemheader, filenames, outputList);
3209+
3210+
if (mLoadCallback && ret.first)
3211+
mLoadCallback(*ret.first, ret.second);
3212+
3213+
return ret;
3214+
}
3215+
32093216
void simplecpp::FileDataCache::clear()
32103217
{
32113218
mImpl->clear();

externals/simplecpp/simplecpp.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ namespace simplecpp {
499499
return mData.cend();
500500
}
501501

502-
using load_callback_type = std::function<void (FileData &)>;
502+
using load_callback_type = std::function<void (FileData &, bool)>;
503503

504504
void set_load_callback(load_callback_type cb) {
505505
mLoadCallback = std::move(cb);
@@ -512,6 +512,7 @@ namespace simplecpp {
512512
using name_map_type = std::unordered_map<std::string, FileData *>;
513513

514514
std::pair<FileData *, bool> tryload(name_map_type::iterator &name_it, const DUI &dui, std::vector<std::string> &filenames, OutputList *outputList);
515+
std::pair<FileData *, bool> get_private(const std::string &sourcefile, const std::string &header, const DUI &dui, bool systemheader, std::vector<std::string> &filenames, OutputList *outputList);
515516

516517
container_type mData;
517518
name_map_type mNameMap;

lib/analyzerinfo.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,63 @@ void AnalyzerInformation::writeFilesTxt(const std::string &buildDir, const std::
5858
fout << getFilesTxt(sourcefiles, fileSettings);
5959
}
6060

61+
void AnalyzerInformation::writeIncludes(const std::set<std::string> &files)
62+
{
63+
if (mOutputStream.is_open()) {
64+
mOutputStream << " <includes>\n";
65+
for (const std::string &file : files) {
66+
mOutputStream << " <filename>" << file << "</filename>\n";
67+
}
68+
mOutputStream << " </includes>\n";
69+
}
70+
}
71+
72+
std::set<std::string> AnalyzerInformation::getIncludes(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg, std::size_t fsFileId)
73+
{
74+
if (mOutputStream.is_open())
75+
throw std::runtime_error("analyzer information file is already open");
76+
77+
std::set<std::string> files;
78+
79+
if (buildDir.empty() || sourcefile.empty())
80+
return files;
81+
82+
const std::string analyzerInfoFile = AnalyzerInformation::getAnalyzerInfoFile(buildDir, sourcefile, cfg, fsFileId);
83+
84+
tinyxml2::XMLDocument analyzerInfoDoc;
85+
const tinyxml2::XMLError xmlError = analyzerInfoDoc.LoadFile(analyzerInfoFile.c_str());
86+
87+
if (analyzerInfoDoc.LoadFile(analyzerInfoFile.c_str()) != tinyxml2::XML_SUCCESS)
88+
return files;
89+
90+
const tinyxml2::XMLElement *const rootNode = analyzerInfoDoc.FirstChildElement();
91+
if (rootNode == nullptr)
92+
return files;
93+
94+
if (strcmp(rootNode->Name(), "analyzerinfo") != 0)
95+
return files;
96+
97+
const tinyxml2::XMLElement *cachedfilesNode = nullptr;
98+
for (const tinyxml2::XMLElement *e = rootNode->FirstChildElement(); e; e = e->NextSiblingElement()) {
99+
if (strcmp(e->Name(), "includes") == 0) {
100+
cachedfilesNode = e;
101+
break;
102+
}
103+
}
104+
105+
if (cachedfilesNode == nullptr)
106+
return files;
107+
108+
for (const tinyxml2::XMLElement *e = cachedfilesNode->FirstChildElement(); e; e = e->NextSiblingElement()) {
109+
if (strcmp(e->Name(), "filename") != 0)
110+
continue;
111+
112+
files.insert(e->GetText());
113+
}
114+
115+
return files;
116+
}
117+
61118
std::string AnalyzerInformation::getFilesTxt(const std::list<std::string> &sourcefiles, const std::list<FileSettings> &fileSettings) {
62119
std::ostringstream ret;
63120

@@ -172,6 +229,7 @@ bool AnalyzerInformation::analyzeFile(const std::string &buildDir, const std::st
172229
tinyxml2::XMLDocument analyzerInfoDoc;
173230
const tinyxml2::XMLError xmlError = analyzerInfoDoc.LoadFile(analyzerInfoFile.c_str());
174231
if (xmlError == tinyxml2::XML_SUCCESS) {
232+
175233
const std::string err = skipAnalysis(analyzerInfoDoc, hash, errors);
176234
if (err.empty()) {
177235
if (debug)

lib/analyzerinfo.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ class CPPCHECKLIB AnalyzerInformation {
6767
bool analyzeFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg, std::size_t fsFileId, std::size_t hash, std::list<ErrorMessage> &errors, bool debug = false);
6868
void reportErr(const ErrorMessage &msg);
6969
void setFileInfo(const std::string &check, const std::string &fileInfo);
70+
void writeIncludes(const std::set<std::string> &files);
71+
std::set<std::string> getIncludes(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg, std::size_t fsFileId);
7072
static std::string getAnalyzerInfoFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg, std::size_t fsFileId);
7173

7274
void reopen(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg, std::size_t fsFileId);

lib/cppcheck.cpp

Lines changed: 46 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,25 +1022,6 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str
10221022
preprocessor.inlineSuppressions(mSuppressions.nomsg);
10231023
preprocessor.removeComments();
10241024

1025-
if (!mSettings.buildDir.empty()) {
1026-
analyzerInformation.reset(new AnalyzerInformation);
1027-
mLogger->setAnalyzerInfo(analyzerInformation.get());
1028-
}
1029-
1030-
if (analyzerInformation) {
1031-
// Calculate hash so it can be compared with old hash / future hashes
1032-
const std::size_t hash = calculateHash(preprocessor, file.spath());
1033-
std::list<ErrorMessage> errors;
1034-
if (!analyzerInformation->analyzeFile(mSettings.buildDir, file.spath(), cfgname, file.fsFileId(), hash, errors, mSettings.debugainfo)) {
1035-
while (!errors.empty()) {
1036-
mErrorLogger.reportErr(errors.front());
1037-
errors.pop_front();
1038-
}
1039-
mLogger->setAnalyzerInfo(nullptr);
1040-
return mLogger->exitcode(); // known results => no need to reanalyze file
1041-
}
1042-
}
1043-
10441025
// Get directives
10451026
std::list<Directive> directives;
10461027
preprocessor.createDirectives(directives);
@@ -1058,26 +1039,57 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str
10581039
std::inserter(configDefines, configDefines.end()),
10591040
getDefineName);
10601041

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);
1042+
// Keep track of all included files
1043+
std::set<std::string> includedFiles;
1044+
1045+
preprocessor.setLoadCallback([&](simplecpp::FileData &data, bool loaded) {
1046+
includedFiles.insert(data.filename);
1047+
if (loaded) {
1048+
// Do preprocessing on included file
1049+
mLogger->addRemarkComments(preprocessor.getRemarkComments(data.tokens));
1050+
preprocessor.inlineSuppressions(data.tokens, mSuppressions.nomsg);
1051+
Preprocessor::removeComments(data.tokens);
1052+
Preprocessor::createDirectives(data.tokens, directives);
1053+
Preprocessor::simplifyPragmaAsm(data.tokens);
1054+
// Discover new configurations from included file
1055+
if (configurations.size() < maxConfigs)
1056+
preprocessor.getConfigs(data.filename, data.tokens, configDefines, configurations);
1057+
}
10711058
});
10721059

10731060
preprocessor.setPlatformInfo();
10741061

1062+
if (!mSettings.buildDir.empty()) {
1063+
analyzerInformation.reset(new AnalyzerInformation);
1064+
mLogger->setAnalyzerInfo(analyzerInformation.get());
1065+
}
1066+
1067+
if (analyzerInformation) {
1068+
// Load all included files so our hash will be correct
1069+
for (const std::string &filename : analyzerInformation->getIncludes(mSettings.buildDir, file.spath(), cfgname, file.fsFileId()))
1070+
preprocessor.loadFile(files, filename);
1071+
// Calculate hash so it can be compared with old hash / future hashes
1072+
const std::size_t hash = calculateHash(preprocessor, file.spath());
1073+
std::list<ErrorMessage> errors;
1074+
if (!analyzerInformation->analyzeFile(mSettings.buildDir, file.spath(), cfgname, file.fsFileId(), hash, errors, mSettings.debugainfo)) {
1075+
while (!errors.empty()) {
1076+
mErrorLogger.reportErr(errors.front());
1077+
errors.pop_front();
1078+
}
1079+
mLogger->setAnalyzerInfo(nullptr);
1080+
return mLogger->exitcode(); // known results => no need to reanalyze file
1081+
}
1082+
// Clear included file list; we don't want to keep includes that have been removed. Any includes
1083+
// that are still present will be readded.
1084+
includedFiles.clear();
1085+
}
1086+
10751087
// Get configurations..
10761088
if (maxConfigs > 1) {
10771089
Timer::run("Preprocessor::getConfigs", mTimerResults, [&]() {
10781090
configurations = { "" };
10791091
preprocessor.getConfigs(configDefines, configurations);
1080-
preprocessor.loadFiles(files);
1092+
preprocessor.loadAllIncludes(files);
10811093
});
10821094
} else {
10831095
configurations = { mSettings.userDefines };
@@ -1300,6 +1312,10 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str
13001312
mLogger->setPlistFilenames(std::move(files));
13011313
}
13021314

1315+
if (analyzerInformation) {
1316+
analyzerInformation->writeIncludes(includedFiles);
1317+
}
1318+
13031319
executeAddons(dumpFile, file);
13041320
} catch (const TerminateException &) {
13051321
// Analysis is terminated

lib/preprocessor.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -833,7 +833,7 @@ const simplecpp::Output* Preprocessor::handleErrors(const simplecpp::OutputList&
833833
return reportOutput(outputList, showerror);
834834
}
835835

836-
bool Preprocessor::loadFiles(std::vector<std::string> &files)
836+
bool Preprocessor::loadAllIncludes(std::vector<std::string> &files)
837837
{
838838
const simplecpp::DUI dui = createDUI(mSettings, "", mLang);
839839

@@ -842,6 +842,13 @@ bool Preprocessor::loadFiles(std::vector<std::string> &files)
842842
return !handleErrors(outputList);
843843
}
844844

845+
simplecpp::FileData *Preprocessor::loadFile(std::vector<std::string> &files, const std::string &file)
846+
{
847+
const simplecpp::DUI dui = createDUI(mSettings, "", mLang);
848+
849+
return mFileCache.get("", file, dui, false, files, nullptr).first;
850+
}
851+
845852
void Preprocessor::removeComments()
846853
{
847854
removeComments(mTokens);

lib/preprocessor.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@ class CPPCHECKLIB WARN_UNUSED Preprocessor {
122122

123123
std::vector<RemarkComment> getRemarkComments(const simplecpp::TokenList &tokens) const;
124124

125-
bool loadFiles(std::vector<std::string> &files);
125+
bool loadAllIncludes(std::vector<std::string> &files);
126+
simplecpp::FileData *Preprocessor::loadFile(std::vector<std::string> &files, const std::string &file);
126127

127128
void removeComments();
128129

@@ -163,6 +164,8 @@ class CPPCHECKLIB WARN_UNUSED Preprocessor {
163164
mFileCache.set_load_callback(std::move(cb));
164165
}
165166

167+
simplecpp::FileDataCache mFileCache;
168+
166169
private:
167170

168171
/**
@@ -182,8 +185,6 @@ class CPPCHECKLIB WARN_UNUSED Preprocessor {
182185
const Settings& mSettings;
183186
ErrorLogger &mErrorLogger;
184187

185-
simplecpp::FileDataCache mFileCache;
186-
187188
/** filename for cpp/c file - useful when reporting errors */
188189
std::string mFile0; // TODO: this is never set
189190
Standards::Language mLang{Standards::Language::None};

test/helpers.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ void SimpleTokenizer2::preprocess(const char* code, std::size_t size, std::vecto
117117
simplecpp::TokenList tokens1({code, size}, files, file0, &outputList);
118118

119119
Preprocessor preprocessor(tokens1, tokenizer.getSettings(), errorlogger, Path::identify(tokens1.getFiles()[0], false));
120-
(void)preprocessor.loadFiles(files); // TODO: check result
120+
(void)preprocessor.loadAllIncludes(files); // TODO: check result
121121
simplecpp::TokenList tokens2 = preprocessor.preprocess("", files, outputList);
122122
(void)preprocessor.reportOutput(outputList, true);
123123

test/testcppcheck.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ class TestCppcheck : public TestFixture {
573573
simplecpp::TokenList tokens(code, files, "m1.c");
574574

575575
Preprocessor preprocessor(tokens, settings, errorLogger, Standards::Language::C);
576-
ASSERT(preprocessor.loadFiles(files));
576+
ASSERT(preprocessor.loadAllIncludes(files));
577577

578578
AddonInfo premiumaddon;
579579
premiumaddon.name = "premiumaddon.json";

test/testpreprocessor.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class TestPreprocessor : public TestFixture {
5959
std::vector<std::string> files;
6060
simplecpp::TokenList tokens1 = simplecpp::TokenList(code, files, "file.cpp", &outputList);
6161
Preprocessor p(tokens1, settingsDefault, errorLogger, Path::identify(tokens1.getFiles()[0], false));
62-
ASSERT_LOC(p.loadFiles(files), file, line);
62+
ASSERT_LOC(p.loadAllIncludes(files), file, line);
6363
simplecpp::TokenList tokens2 = p.preprocess("", files, outputList);
6464
(void)p.reportOutput(outputList, true);
6565
return tokens2.stringify();
@@ -410,13 +410,13 @@ class TestPreprocessor : public TestFixture {
410410
settings.library.defines().end(),
411411
std::inserter(configDefines, configDefines.end()),
412412
getDefineName);
413-
preprocessor.setLoadCallback([&](simplecpp::FileData &data) {
413+
preprocessor.setLoadCallback([&](simplecpp::FileData &data, bool) {
414414
Preprocessor::removeComments(data.tokens);
415415
preprocessor.getConfigs(data.filename, data.tokens, configDefines, configs);
416416
});
417417
preprocessor.removeComments();
418418
preprocessor.getConfigs(configDefines, configs);
419-
ASSERT(preprocessor.loadFiles(files));
419+
ASSERT(preprocessor.loadAllIncludes(files));
420420
ASSERT(!preprocessor.reportOutput(outputList, true));
421421
std::string ret;
422422
for (const std::string & config : configs)
@@ -429,11 +429,11 @@ class TestPreprocessor : public TestFixture {
429429
std::vector<std::string> files;
430430
simplecpp::TokenList tokens(code,files,"test.c");
431431
Preprocessor preprocessor(tokens, settingsDefault, *this, Standards::Language::C);
432-
preprocessor.setLoadCallback([](simplecpp::FileData &data) {
432+
preprocessor.setLoadCallback([](simplecpp::FileData &data, bool) {
433433
Preprocessor::removeComments(data.tokens);
434434
});
435435
preprocessor.removeComments();
436-
ASSERT(preprocessor.loadFiles(files));
436+
ASSERT(preprocessor.loadAllIncludes(files));
437437
return preprocessor.calculateHash("");
438438
}
439439

0 commit comments

Comments
 (0)