Skip to content

Commit 35071e5

Browse files
committed
Fix #13333
1 parent ebc80c0 commit 35071e5

17 files changed

+219
-63
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -701,7 +701,7 @@ test/options.o: test/options.cpp test/options.h
701701
test/test64bit.o: test/test64bit.cpp lib/addoninfo.h lib/check.h lib/check64bit.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h
702702
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/test64bit.cpp
703703

704-
test/testanalyzerinformation.o: test/testanalyzerinformation.cpp lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h
704+
test/testanalyzerinformation.o: test/testanalyzerinformation.cpp lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/utils.h test/fixture.h
705705
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testanalyzerinformation.cpp
706706

707707
test/testassert.o: test/testassert.cpp lib/addoninfo.h lib/check.h lib/checkassert.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h

gui/checkthread.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ void CheckThread::runAddonsAndTools(const Settings& settings, const FileSettings
245245

246246
const std::string &buildDir = settings.buildDir;
247247
if (!buildDir.empty()) {
248-
analyzerInfoFile = QString::fromStdString(AnalyzerInformation::getAnalyzerInfoFile(buildDir, fileSettings->filename(), fileSettings->cfg));
248+
analyzerInfoFile = QString::fromStdString(AnalyzerInformation::getAnalyzerInfoFile(buildDir, fileSettings->filename(), fileSettings->cfg, fileSettings->fileIndex));
249249

250250
QStringList args2(args);
251251
args2.insert(0,"-E");

lib/analyzerinfo.cpp

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
#include <cstring>
2727
#include <map>
28+
#include <sstream>
2829

2930
#include "xml.h"
3031

@@ -47,21 +48,30 @@ static std::string getFilename(const std::string &fullpath)
4748

4849
void AnalyzerInformation::writeFilesTxt(const std::string &buildDir, const std::list<std::string> &sourcefiles, const std::string &userDefines, const std::list<FileSettings> &fileSettings)
4950
{
50-
std::map<std::string, unsigned int> fileCount;
51-
5251
const std::string filesTxt(buildDir + "/files.txt");
5352
std::ofstream fout(filesTxt);
53+
fout << getFilesTxt(sourcefiles, userDefines, fileSettings);
54+
}
55+
56+
std::string AnalyzerInformation::getFilesTxt(const std::list<std::string> &sourcefiles, const std::string &userDefines, const std::list<FileSettings> &fileSettings) {
57+
std::ostringstream ret;
58+
59+
std::map<std::string, unsigned int> fileCount;
60+
5461
for (const std::string &f : sourcefiles) {
5562
const std::string afile = getFilename(f);
56-
fout << afile << ".a" << (++fileCount[afile]) << "::" << Path::simplifyPath(f) << '\n';
63+
ret << afile << ".a" << (++fileCount[afile]) << sep << sep << sep << Path::simplifyPath(f) << '\n';
5764
if (!userDefines.empty())
58-
fout << afile << ".a" << (++fileCount[afile]) << ":" << userDefines << ":" << Path::simplifyPath(f) << '\n';
65+
ret << afile << ".a" << (++fileCount[afile]) << sep << userDefines << sep << sep << Path::simplifyPath(f) << '\n';
5966
}
6067

6168
for (const FileSettings &fs : fileSettings) {
6269
const std::string afile = getFilename(fs.filename());
63-
fout << afile << ".a" << (++fileCount[afile]) << ":" << fs.cfg << ":" << Path::simplifyPath(fs.filename()) << std::endl;
70+
const std::string id = fs.fileIndex > 0 ? std::to_string(fs.fileIndex) : "";
71+
ret << afile << ".a" << (++fileCount[afile]) << sep << fs.cfg << sep << id << sep << Path::simplifyPath(fs.filename()) << std::endl;
6472
}
73+
74+
return ret.str();
6575
}
6676

6777
void AnalyzerInformation::close()
@@ -96,25 +106,26 @@ static bool skipAnalysis(const std::string &analyzerInfoFile, std::size_t hash,
96106
return true;
97107
}
98108

99-
std::string AnalyzerInformation::getAnalyzerInfoFileFromFilesTxt(std::istream& filesTxt, const std::string &sourcefile, const std::string &cfg)
109+
std::string AnalyzerInformation::getAnalyzerInfoFileFromFilesTxt(std::istream& filesTxt, const std::string &sourcefile, const std::string &cfg, int fileIndex)
100110
{
111+
const std::string id = (fileIndex > 0) ? std::to_string(fileIndex) : "";
101112
std::string line;
102-
const std::string end(':' + cfg + ':' + Path::simplifyPath(sourcefile));
113+
const std::string end(sep + cfg + sep + id + sep + Path::simplifyPath(sourcefile));
103114
while (std::getline(filesTxt,line)) {
104115
if (line.size() <= end.size() + 2U)
105116
continue;
106117
if (!endsWith(line, end.c_str(), end.size()))
107118
continue;
108-
return line.substr(0,line.find(':'));
119+
return line.substr(0,line.find(sep));
109120
}
110121
return "";
111122
}
112123

113-
std::string AnalyzerInformation::getAnalyzerInfoFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg)
124+
std::string AnalyzerInformation::getAnalyzerInfoFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg, int fileIndex)
114125
{
115126
std::ifstream fin(Path::join(buildDir, "files.txt"));
116127
if (fin.is_open()) {
117-
const std::string& ret = getAnalyzerInfoFileFromFilesTxt(fin, sourcefile, cfg);
128+
const std::string& ret = getAnalyzerInfoFileFromFilesTxt(fin, sourcefile, cfg, fileIndex);
118129
if (!ret.empty())
119130
return Path::join(buildDir, ret);
120131
}
@@ -128,13 +139,13 @@ std::string AnalyzerInformation::getAnalyzerInfoFile(const std::string &buildDir
128139
return Path::join(buildDir, filename) + ".analyzerinfo";
129140
}
130141

131-
bool AnalyzerInformation::analyzeFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg, std::size_t hash, std::list<ErrorMessage> &errors)
142+
bool AnalyzerInformation::analyzeFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg, int fileIndex, std::size_t hash, std::list<ErrorMessage> &errors)
132143
{
133144
if (buildDir.empty() || sourcefile.empty())
134145
return true;
135146
close();
136147

137-
mAnalyzerInfoFile = AnalyzerInformation::getAnalyzerInfoFile(buildDir,sourcefile,cfg);
148+
mAnalyzerInfoFile = AnalyzerInformation::getAnalyzerInfoFile(buildDir,sourcefile,cfg,fileIndex);
138149

139150
if (skipAnalysis(mAnalyzerInfoFile, hash, errors))
140151
return false;
@@ -161,3 +172,33 @@ void AnalyzerInformation::setFileInfo(const std::string &check, const std::strin
161172
if (mOutputStream.is_open() && !fileInfo.empty())
162173
mOutputStream << " <FileInfo check=\"" << check << "\">\n" << fileInfo << " </FileInfo>\n";
163174
}
175+
176+
bool AnalyzerInformation::Info::parse(const std::string& filesTxtLine) {
177+
const std::string::size_type sep1 = filesTxtLine.find(sep);
178+
if (sep1 == std::string::npos)
179+
return false;
180+
const std::string::size_type sep2 = filesTxtLine.find(sep, sep1+1);
181+
if (sep2 == std::string::npos)
182+
return false;
183+
const std::string::size_type sep3 = filesTxtLine.find(sep, sep2+1);
184+
if (sep3 == std::string::npos)
185+
return false;
186+
if (filesTxtLine.find(sep, sep3+1) != std::string::npos)
187+
return false;
188+
189+
if (sep3 == sep2 + 1)
190+
fileIndex = 0;
191+
else {
192+
try {
193+
fileIndex = std::stoi(filesTxtLine.substr(sep2+1, sep3-sep2-1));
194+
} catch (const std::exception&) {
195+
return false;
196+
}
197+
}
198+
199+
afile = filesTxtLine.substr(0, sep1);
200+
cfg = filesTxtLine.substr(sep1+1, sep2-sep1-1);
201+
sourceFile = filesTxtLine.substr(sep3+1);
202+
return true;
203+
}
204+

lib/analyzerinfo.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,29 @@ class CPPCHECKLIB AnalyzerInformation {
5151
public:
5252
~AnalyzerInformation();
5353

54+
static std::string getFilesTxt(const std::list<std::string> &sourcefiles, const std::string &userDefines, const std::list<FileSettings> &fileSettings);
55+
5456
static void writeFilesTxt(const std::string &buildDir, const std::list<std::string> &sourcefiles, const std::string &userDefines, const std::list<FileSettings> &fileSettings);
5557

5658
/** Close current TU.analyzerinfo file */
5759
void close();
58-
bool analyzeFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg, std::size_t hash, std::list<ErrorMessage> &errors);
60+
bool analyzeFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg, int fileIndex, std::size_t hash, std::list<ErrorMessage> &errors);
5961
void reportErr(const ErrorMessage &msg);
6062
void setFileInfo(const std::string &check, const std::string &fileInfo);
61-
static std::string getAnalyzerInfoFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg);
63+
static std::string getAnalyzerInfoFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg, int fileIndex);
64+
65+
static const char sep = '\t';
66+
67+
struct Info {
68+
bool parse(const std::string& filesTxtLine);
69+
std::string afile;
70+
std::string cfg;
71+
int fileIndex = 0;
72+
std::string sourceFile;
73+
};
74+
6275
protected:
63-
static std::string getAnalyzerInfoFileFromFilesTxt(std::istream& filesTxt, const std::string &sourcefile, const std::string &cfg);
76+
static std::string getAnalyzerInfoFileFromFilesTxt(std::istream& filesTxt, const std::string &sourcefile, const std::string &cfg, int fileIndex);
6477
private:
6578
std::ofstream mOutputStream;
6679
std::string mAnalyzerInfoFile;

lib/cppcheck.cpp

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -331,16 +331,16 @@ static std::vector<std::string> split(const std::string &str, const std::string
331331
return ret;
332332
}
333333

334-
static std::string getDumpFileName(const Settings& settings, const std::string& filename)
334+
static std::string getDumpFileName(const Settings& settings, const std::string& filename, int fileIndex)
335335
{
336-
std::string extension;
337-
if (settings.dump || !settings.buildDir.empty())
338-
extension = ".dump";
339-
else
340-
extension = "." + std::to_string(settings.pid) + ".dump";
336+
std::string extension = ".dump";
337+
if (fileIndex > 0)
338+
extension = "." + std::to_string(fileIndex) + extension;
339+
if (!settings.dump && settings.buildDir.empty())
340+
extension = "." + std::to_string(settings.pid) + extension;
341341

342342
if (!settings.dump && !settings.buildDir.empty())
343-
return AnalyzerInformation::getAnalyzerInfoFile(settings.buildDir, filename, "") + extension;
343+
return AnalyzerInformation::getAnalyzerInfoFile(settings.buildDir, filename, "", fileIndex) + extension;
344344
return filename + extension;
345345
}
346346

@@ -351,12 +351,13 @@ static std::string getCtuInfoFileName(const std::string &dumpFile)
351351

352352
static void createDumpFile(const Settings& settings,
353353
const FileWithDetails& file,
354+
int fileIndex,
354355
std::ofstream& fdump,
355356
std::string& dumpFile)
356357
{
357358
if (!settings.dump && settings.addons.empty())
358359
return;
359-
dumpFile = getDumpFileName(settings, file.spath());
360+
dumpFile = getDumpFileName(settings, file.spath(), fileIndex);
360361

361362
fdump.open(dumpFile);
362363
if (!fdump.is_open())
@@ -649,7 +650,7 @@ static std::string getClangFlags(const Settings& setting, Standards::Language la
649650
}
650651

651652
// TODO: clear error list before returning
652-
unsigned int CppCheck::checkClang(const FileWithDetails &file)
653+
unsigned int CppCheck::checkClang(const FileWithDetails &file, int fileIndex)
653654
{
654655
// TODO: clear exitcode
655656

@@ -662,7 +663,7 @@ unsigned int CppCheck::checkClang(const FileWithDetails &file)
662663
// TODO: get language from FileWithDetails object
663664
std::string clangStderr;
664665
if (!mSettings.buildDir.empty())
665-
clangStderr = AnalyzerInformation::getAnalyzerInfoFile(mSettings.buildDir, file.spath(), "") + ".clang-stderr";
666+
clangStderr = AnalyzerInformation::getAnalyzerInfoFile(mSettings.buildDir, file.spath(), "", fileIndex) + ".clang-stderr";
666667

667668
std::string exe = mSettings.clangExecutable;
668669
#ifdef _WIN32
@@ -732,7 +733,7 @@ unsigned int CppCheck::checkClang(const FileWithDetails &file)
732733
// create dumpfile
733734
std::ofstream fdump;
734735
std::string dumpFile;
735-
createDumpFile(mSettings, file, fdump, dumpFile);
736+
createDumpFile(mSettings, file, fileIndex, fdump, dumpFile);
736737
if (fdump.is_open()) {
737738
fdump << getLibraryDumpData();
738739
// TODO: use tinyxml2 to create XML
@@ -776,9 +777,9 @@ unsigned int CppCheck::check(const FileWithDetails &file)
776777

777778
unsigned int returnValue;
778779
if (mSettings.clang)
779-
returnValue = checkClang(file);
780+
returnValue = checkClang(file, 0);
780781
else
781-
returnValue = checkFile(file, "");
782+
returnValue = checkFile(file, "", 0);
782783

783784
// TODO: call analyseClangTidy()
784785

@@ -788,7 +789,7 @@ unsigned int CppCheck::check(const FileWithDetails &file)
788789
unsigned int CppCheck::check(const FileWithDetails &file, const std::string &content)
789790
{
790791
std::istringstream iss(content);
791-
return checkFile(file, "", &iss);
792+
return checkFile(file, "", 0, &iss);
792793
}
793794

794795
unsigned int CppCheck::check(const FileSettings &fs)
@@ -824,7 +825,7 @@ unsigned int CppCheck::check(const FileSettings &fs)
824825
}
825826
// need to pass the externally provided ErrorLogger instead of our internal wrapper
826827
CppCheck temp(tempSettings, mSuppressions, mErrorLoggerDirect, mUseGlobalSuppressions, mExecuteCommand);
827-
const unsigned int returnValue = temp.checkFile(fs.file, fs.cfg);
828+
const unsigned int returnValue = temp.checkFile(fs.file, fs.cfg, fs.fileIndex);
828829
if (mUnusedFunctionsCheck)
829830
mUnusedFunctionsCheck->updateFunctionData(*temp.mUnusedFunctionsCheck);
830831
while (!temp.mFileInfo.empty()) {
@@ -861,7 +862,7 @@ static std::size_t calculateHash(const Preprocessor& preprocessor, const simplec
861862
return preprocessor.calculateHash(tokens, toolinfo.str());
862863
}
863864

864-
unsigned int CppCheck::checkFile(const FileWithDetails& file, const std::string &cfgname, std::istream* fileStream)
865+
unsigned int CppCheck::checkFile(const FileWithDetails& file, const std::string &cfgname, int fileIndex, std::istream* fileStream)
865866
{
866867
// TODO: move to constructor when CppCheck no longer owns the settings
867868
if (mSettings.checks.isEnabled(Checks::unusedFunction) && !mUnusedFunctionsCheck)
@@ -938,7 +939,7 @@ unsigned int CppCheck::checkFile(const FileWithDetails& file, const std::string
938939
mLogger->setAnalyzerInfo(nullptr);
939940

940941
std::list<ErrorMessage> errors;
941-
analyzerInformation->analyzeFile(mSettings.buildDir, file.spath(), cfgname, hash, errors);
942+
analyzerInformation->analyzeFile(mSettings.buildDir, file.spath(), cfgname, fileIndex, hash, errors);
942943
analyzerInformation->setFileInfo("CheckUnusedFunctions", mUnusedFunctionsCheck->analyzerInfo(tokenizer));
943944
analyzerInformation->close();
944945
}
@@ -1012,7 +1013,7 @@ unsigned int CppCheck::checkFile(const FileWithDetails& file, const std::string
10121013
// Calculate hash so it can be compared with old hash / future hashes
10131014
const std::size_t hash = calculateHash(preprocessor, tokens1, mSettings, mSuppressions);
10141015
std::list<ErrorMessage> errors;
1015-
if (!analyzerInformation->analyzeFile(mSettings.buildDir, file.spath(), cfgname, hash, errors)) {
1016+
if (!analyzerInformation->analyzeFile(mSettings.buildDir, file.spath(), cfgname, fileIndex, hash, errors)) {
10161017
while (!errors.empty()) {
10171018
mErrorLogger.reportErr(errors.front());
10181019
errors.pop_front();
@@ -1075,7 +1076,7 @@ unsigned int CppCheck::checkFile(const FileWithDetails& file, const std::string
10751076
// write dump file xml prolog
10761077
std::ofstream fdump;
10771078
std::string dumpFile;
1078-
createDumpFile(mSettings, file, fdump, dumpFile);
1079+
createDumpFile(mSettings, file, fileIndex, fdump, dumpFile);
10791080
if (fdump.is_open()) {
10801081
fdump << getLibraryDumpData();
10811082
fdump << dumpProlog;
@@ -1170,7 +1171,7 @@ unsigned int CppCheck::checkFile(const FileWithDetails& file, const std::string
11701171
#endif
11711172

11721173
// Simplify tokens into normal form, skip rest of iteration if failed
1173-
if (!tokenizer.simplifyTokens1(currentConfig))
1174+
if (!tokenizer.simplifyTokens1(currentConfig, fileIndex))
11741175
continue;
11751176

11761177
// dump xml if --dump
@@ -1812,12 +1813,12 @@ void CppCheck::executeAddonsWholeProgram(const std::list<FileWithDetails> &files
18121813

18131814
std::vector<std::string> ctuInfoFiles;
18141815
for (const auto &f: files) {
1815-
const std::string &dumpFileName = getDumpFileName(mSettings, f.path());
1816+
const std::string &dumpFileName = getDumpFileName(mSettings, f.path(), 0);
18161817
ctuInfoFiles.push_back(getCtuInfoFileName(dumpFileName));
18171818
}
18181819

18191820
for (const auto &f: fileSettings) {
1820-
const std::string &dumpFileName = getDumpFileName(mSettings, f.filename());
1821+
const std::string &dumpFileName = getDumpFileName(mSettings, f.filename(), f.fileIndex);
18211822
ctuInfoFiles.push_back(getCtuInfoFileName(dumpFileName));
18221823
}
18231824

@@ -1944,7 +1945,7 @@ void CppCheck::analyseClangTidy(const FileSettings &fileSettings)
19441945
std::string line;
19451946

19461947
if (!mSettings.buildDir.empty()) {
1947-
const std::string analyzerInfoFile = AnalyzerInformation::getAnalyzerInfoFile(mSettings.buildDir, fileSettings.filename(), "");
1948+
const std::string analyzerInfoFile = AnalyzerInformation::getAnalyzerInfoFile(mSettings.buildDir, fileSettings.filename(), "", fileSettings.fileIndex);
19481949
std::ofstream fcmd(analyzerInfoFile + ".clang-tidy-cmd");
19491950
fcmd << istr.str();
19501951
}
@@ -2036,14 +2037,11 @@ unsigned int CppCheck::analyseWholeProgram(const std::string &buildDir, const st
20362037
std::ifstream fin(filesTxt);
20372038
std::string filesTxtLine;
20382039
while (std::getline(fin, filesTxtLine)) {
2039-
const std::string::size_type firstColon = filesTxtLine.find(':');
2040-
if (firstColon == std::string::npos)
2041-
continue;
2042-
const std::string::size_type lastColon = filesTxtLine.rfind(':');
2043-
if (firstColon == lastColon)
2040+
AnalyzerInformation::Info filesTxtInfo;
2041+
if (!filesTxtInfo.parse(filesTxtLine))
20442042
continue;
2045-
const std::string xmlfile = buildDir + '/' + filesTxtLine.substr(0,firstColon);
2046-
//const std::string sourcefile = filesTxtLine.substr(lastColon+1);
2043+
2044+
const std::string xmlfile = buildDir + '/' + filesTxtInfo.afile;
20472045

20482046
tinyxml2::XMLDocument doc;
20492047
const tinyxml2::XMLError error = doc.LoadFile(xmlfile.c_str());
@@ -2068,7 +2066,7 @@ unsigned int CppCheck::analyseWholeProgram(const std::string &buildDir, const st
20682066
for (const Check *check : Check::instances()) {
20692067
if (checkClassAttr == check->name()) {
20702068
Check::FileInfo* fi = check->loadFileInfoFromXml(e);
2071-
fi->file0 = filesTxtLine.substr(firstColon + 2);
2069+
fi->file0 = filesTxtInfo.sourceFile;
20722070
fileInfoList.push_back(fi);
20732071
}
20742072
}

lib/cppcheck.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ class CPPCHECKLIB CppCheck {
169169
* @param fileStream stream the file content can be read from
170170
* @return number of errors found
171171
*/
172-
unsigned int checkFile(const FileWithDetails& file, const std::string &cfgname, std::istream* fileStream = nullptr);
172+
unsigned int checkFile(const FileWithDetails& file, const std::string &cfgname, int fileIndex, std::istream* fileStream = nullptr);
173173

174174
/**
175175
* @brief Check normal tokens
@@ -198,7 +198,7 @@ class CPPCHECKLIB CppCheck {
198198
void executeRules(const std::string &tokenlist, const TokenList &list);
199199
#endif
200200

201-
unsigned int checkClang(const FileWithDetails &file);
201+
unsigned int checkClang(const FileWithDetails &file, int fileIndex);
202202

203203
const Settings& mSettings;
204204
Suppressions& mSuppressions;

0 commit comments

Comments
 (0)